diff options
Diffstat (limited to 'chromium/chrome/browser/resources')
311 files changed, 8503 insertions, 5730 deletions
diff --git a/chromium/chrome/browser/resources/BUILD.gn b/chromium/chrome/browser/resources/BUILD.gn index c5f813e5c89..0f428df836e 100644 --- a/chromium/chrome/browser/resources/BUILD.gn +++ b/chromium/chrome/browser/resources/BUILD.gn @@ -6,12 +6,13 @@ import("//chrome/common/features.gni") import("//chrome/test/base/js2gtest.gni") import("//chrome/test/include_js_tests.gni") import("//components/nacl/features.gni") +import("//third_party/closure_compiler/compile_js.gni") import("//tools/grit/grit_rule.gni") import("//tools/grit/repack.gni") assert(!is_ios, "Chromium/iOS shouldn't use anything in //chrome") -if (closure_compile) { +if (enable_js_type_check) { group("closure_compile") { deps = [ "components:closure_compile", @@ -34,6 +35,8 @@ if (closure_compile) { "local_state:closure_compile", "management:closure_compile", "media_router:closure_compile", + "nearby_internals:closure_compile", + "nearby_share:closure_compile", "new_tab_page:closure_compile", "ntp4:closure_compile", "omnibox:closure_compile", @@ -45,6 +48,7 @@ if (closure_compile) { "signin:closure_compile", "usb_internals:closure_compile", "user_manager:closure_compile", + "web_app_internals:closure_compile", "welcome:closure_compile", ] } @@ -67,6 +71,7 @@ if (closure_compile) { deps += [ "explore_sites_internals:closure_compile", "feed_internals:closure_compile", + "internals/query_tiles:closure_compile", "offline_pages:closure_compile", "snippets_internals:closure_compile", "webapks:closure_compile", @@ -121,7 +126,7 @@ if (!is_android) { "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), ] - deps = [ "//chrome/browser/resources/pdf/elements:web_components" ] + deps = [ "//chrome/browser/resources/pdf:web_components" ] defines = chrome_grit_defines if (enable_hangout_services_extension) { @@ -192,6 +197,46 @@ if (!is_android) { output_dir = "$root_gen_dir/chrome" } + grit("nearby_internals_resources") { + source = "nearby_internals/nearby_internals_resources.grd" + + grit_flags = [ + "-E", + "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), + ] + + deps = [ "//chrome/browser/resources/nearby_internals:web_components" ] + + defines = chrome_grit_defines + outputs = [ + "grit/nearby_internals_resources.h", + "grit/nearby_internals_resources_map.cc", + "grit/nearby_internals_resources_map.h", + "nearby_internals_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" + } + + grit("nearby_share_dialog_resources") { + source = "nearby_share/nearby_share_dialog_resources.grd" + + grit_flags = [ + "-E", + "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), + ] + + deps = [ "//chrome/browser/resources/nearby_share:web_components" ] + + defines = chrome_grit_defines + outputs = [ + "grit/nearby_share_dialog_resources.h", + "grit/nearby_share_dialog_resources_map.cc", + "grit/nearby_share_dialog_resources_map.h", + "nearby_share_dialog_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" + } + grit("new_tab_page_resources") { if (optimize_webui) { source = "new_tab_page/new_tab_page_resources_vulcanized.grd" @@ -289,11 +334,16 @@ if (is_chromeos) { enable_input_discovery_for_gn_analyze = false source = "settings/os_settings_resources_vulcanized.grd" - deps += [ "//chrome/browser/resources/settings/chromeos:build" ] + deps += [ + "//chrome/browser/resources/settings/chromeos:build", + "//chrome/browser/resources/settings/chromeos:build_polymer3", + ] } else { source = "settings/os_settings_resources.grd" - deps += - [ "//chrome/browser/resources/settings/chromeos:polymer3_elements" ] + deps += [ + "//chrome/browser/resources/settings/chromeos:polymer3_elements", + "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings_js", + ] } defines = chrome_grit_defines @@ -305,6 +355,34 @@ if (is_chromeos) { ] output_dir = "$root_gen_dir/chrome" } + + grit("bluetooth_pairing_dialog_resources") { + grit_flags = [ + "-E", + "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), + ] + + if (optimize_webui) { + source = "chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources_vulcanized.grd" + + deps = [ + "//chrome/browser/resources/chromeos/bluetooth_pairing_dialog:build", + ] + } else { + source = "chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd" + + deps = [ "//chrome/browser/resources/chromeos/bluetooth_pairing_dialog:web_components" ] + } + + defines = chrome_grit_defines + outputs = [ + "grit/bluetooth_pairing_dialog_resources.h", + "grit/bluetooth_pairing_dialog_resources_map.cc", + "grit/bluetooth_pairing_dialog_resources_map.h", + "bluetooth_pairing_dialog_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" + } } if (!is_android && !is_chromeos) { @@ -330,6 +408,7 @@ if (!is_android && !is_chromeos) { grit("profile_picker_resources") { source = "signin/profile_picker/profile_picker_resources.grd" + deps = [ "//chrome/browser/resources/signin/profile_picker:web_components" ] grit_flags = [ "-E", "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), @@ -393,16 +472,10 @@ if (enable_print_preview) { if (optimize_webui) { source = "print_preview/print_preview_resources_vulcanized.grd" - deps = [ - "//chrome/browser/resources/pdf/elements:web_components", - "//chrome/browser/resources/print_preview:build", - ] + deps = [ "//chrome/browser/resources/print_preview:build" ] } else { source = "print_preview/print_preview_resources.grd" - deps = [ - "//chrome/browser/resources/pdf/elements:web_components", - "//chrome/browser/resources/print_preview/ui:web_components", - ] + deps = [ "//chrome/browser/resources/print_preview/ui:web_components" ] } defines = chrome_grit_defines @@ -414,6 +487,25 @@ if (enable_print_preview) { ] output_dir = "$root_gen_dir/chrome" } + + grit("print_preview_pdf_resources") { + grit_flags = [ + "-E", + "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), + ] + + source = "print_preview/print_preview_pdf_resources.grd" + deps = [ "//chrome/browser/resources/pdf:web_components" ] + + defines = chrome_grit_defines + outputs = [ + "grit/print_preview_pdf_resources.h", + "grit/print_preview_pdf_resources_map.cc", + "grit/print_preview_pdf_resources_map.h", + "print_preview_pdf_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" + } } if (enable_webui_tab_strip) { diff --git a/chromium/chrome/browser/resources/accessibility/accessibility.html b/chromium/chrome/browser/resources/accessibility/accessibility.html index 1d9b645429c..6e77f7bbfe5 100644 --- a/chromium/chrome/browser/resources/accessibility/accessibility.html +++ b/chromium/chrome/browser/resources/accessibility/accessibility.html @@ -111,23 +111,6 @@ found in the LICENSE file. <div id="label_images_secondary" class="secondary"> Automatically labels images. </div> - - <h2>Command line options:</h2> - <p> - Accessibility features in Chrome are off by default and enabled - automatically on-demand. Changes to these modes only take effect - until the next time Chrome is restarted. - </p> - <p> - To force accessibility to be enabled at launch, run Chrome with this - flag: - <pre>--force-renderer-accessibility</pre> - </p> - <p> - To disable accessibility, run Chrome with this flag: - <pre>--disable-renderer-accessibility</pre> - </p> - </div> <div class="column"> <h2>Accessibility tree viewing options:</h2> @@ -181,14 +164,36 @@ found in the LICENSE file. <div id="deny_secondary" class="secondary"> Exclude these attributes. </div> + </div> + </div> + <div class="columns"> + <div class="column"> + <h2>Command line options:</h2> + <p> + Accessibility features in Chrome are off by default and enabled + automatically on-demand. Changes to these modes only take effect + until the next time Chrome is restarted. + </p> + <p> + To force accessibility to be enabled at launch, run Chrome with this + flag: + <pre>--force-renderer-accessibility</pre> + </p> + <p> + To disable accessibility, run Chrome with this flag: + <pre>--disable-renderer-accessibility</pre> + </p> </div> </div> <h2>Chrome Native UI:</h2> <div id="browsers" class="list"> - Set a delay, in milliseconds, before getting the native accessibility tree: - <input type="number" value="0" id="native_ui_delay"> ms + <label for="native-ui-delay"> + Set a delay, in milliseconds, before getting the native accessibility + tree: + </label> + <input id="native-ui-delay" type="number" value="0"> ms </div> <h2>Pages:</h2> diff --git a/chromium/chrome/browser/resources/accessibility/accessibility.js b/chromium/chrome/browser/resources/accessibility/accessibility.js index b6ac8513857..d0b0b7f9b92 100644 --- a/chromium/chrome/browser/resources/accessibility/accessibility.js +++ b/chromium/chrome/browser/resources/accessibility/accessibility.js @@ -6,7 +6,7 @@ cr.define('accessibility', function() { 'use strict'; // Note: keep these values in sync with the values in - // content/common/accessibility_mode_enums.h + // ui/accessibility/ax_mode.h const AXMode = { kNativeAPIs: 1 << 0, kWebContents: 1 << 1, @@ -14,6 +14,7 @@ cr.define('accessibility', function() { kScreenReader: 1 << 3, kHTML: 1 << 4, kLabelImages: 1 << 5, + kPDF: 1 << 6, get kAXModeWebContentsOnly() { return AXMode.kWebContents | AXMode.kInlineTextBoxes | @@ -229,6 +230,7 @@ cr.define('accessibility', function() { row.appendChild(createModeElement(AXMode.kHTML, data, 'web')); row.appendChild( createModeElement(AXMode.kLabelImages, data, 'labelImages')); + row.appendChild(createModeElement(AXMode.kPDF, data, 'pdf')); } else { const siteInfo = document.createElement('span'); siteInfo.appendChild(formatValue(data, 'name')); @@ -313,6 +315,8 @@ cr.define('accessibility', function() { return 'HTML'; case AXMode.kLabelImages: return 'Label images'; + case AXMode.kPDF: + return 'PDF'; } return 'unknown'; } diff --git a/chromium/chrome/browser/resources/bluetooth_internals/resources.grd b/chromium/chrome/browser/resources/bluetooth_internals/resources.grd index 8285a4f76f3..7784acd724c 100644 --- a/chromium/chrome/browser/resources/bluetooth_internals/resources.grd +++ b/chromium/chrome/browser/resources/bluetooth_internals/resources.grd @@ -18,127 +18,98 @@ <includes> <include name="IDR_BLUETOOTH_INTERNALS_ADAPTER_BROKER_JS" file="adapter_broker.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_ADAPTER_MOJO_JS" file="${root_gen_dir}\device\bluetooth\public\mojom\adapter.mojom-lite.js" use_base_dir="false" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_ADAPTER_PAGE_JS" file="adapter_page.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_DEBUG_LOG_PAGE_JS" file="debug_log_page.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_CHARACTERISTIC_LIST_JS" file="characteristic_list.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_CSS" file="bluetooth_internals.css" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_DESCRIPTOR_LIST_JS" file="descriptor_list.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_DEVICE_BROKER_JS" file="device_broker.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_DEVICE_COLLECTION_JS" file="device_collection.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_DEVICE_DETAILS_PAGE_JS" file="device_details_page.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_DEVICE_MOJO_JS" file="${root_gen_dir}\device\bluetooth\public\mojom\device.mojom-lite.js" use_base_dir="false" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_DEVICE_TABLE_JS" file="device_table.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_DEVICES_PAGE_JS" file="devices_page.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_EXPANDABLE_LIST_JS" file="expandable_list.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_HTML" file="bluetooth_internals.html" flattenhtml="true" allowexternalscript="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_JS" file="bluetooth_internals.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\bluetooth_internals\bluetooth_internals.mojom-lite.js" use_base_dir="false" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_NODE_UTILS_HTML" file="node_utils.html" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_NODE_UTILS_JS" file="node_utils.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_OBJECT_FIELDSET_JS" file="object_fieldset.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_PAGE_MANAGER_HTML" file="page_manager.html" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_PAGE_MANAGER_JS" file="page_manager.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_PAGE_HTML" file="page.html" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_PAGE_JS" file="page.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_SERVICE_LIST_JS" file="service_list.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_SIDEBAR_JS" file="sidebar.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_SNACKBAR_JS" file="snackbar.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_UUID_MOJO_JS" file="${root_gen_dir}\device\bluetooth\public\mojom\uuid.mojom-lite.js" use_base_dir="false" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_BLUETOOTH_INTERNALS_VALUE_CONTROL_JS" file="value_control.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/bookmarks/BUILD.gn b/chromium/chrome/browser/resources/bookmarks/BUILD.gn index 3c241d44826..d85d90a82aa 100644 --- a/chromium/chrome/browser/resources/bookmarks/BUILD.gn +++ b/chromium/chrome/browser/resources/bookmarks/BUILD.gn @@ -101,7 +101,8 @@ js_library("actions") { "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js/cr/ui:store.m", ] - externs_list = [ "$externs_path/chrome_extensions.js" ] + + externs_list = [ "$externs_path/bookmarks.js" ] } js_library("api_listener") { @@ -115,7 +116,8 @@ js_library("api_listener") { "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js/cr/ui:store.m", ] - externs_list = [ "$externs_path/chrome_extensions.js" ] + + externs_list = [ "$externs_path/bookmarks.js" ] } js_library("app") { @@ -131,7 +133,10 @@ js_library("app") { "//ui/webui/resources/js:find_shortcut_behavior.m", "//ui/webui/resources/js:load_time_data.m", ] - externs_list = [ "$externs_path/chrome_extensions.js" ] + externs_list = [ + "$externs_path/bookmarks.js", + "$externs_path/metrics_private.js", + ] } js_library("browser_proxy") { @@ -160,7 +165,10 @@ js_library("command_manager") { "//ui/webui/resources/js:load_time_data.m", "//ui/webui/resources/js/cr/ui:keyboard_shortcut_list.m", ] - externs_list = [ "$externs_path/bookmark_manager_private.js" ] + externs_list = chrome_extension_public_externs + [ + "$externs_path/bookmark_manager_private.js", + "$externs_path/bookmarks.js", + ] } js_library("constants") { @@ -203,7 +211,7 @@ js_library("edit_dialog") { "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", ] - externs_list = [ "$externs_path/chrome_extensions.js" ] + externs_list = [ "$externs_path/bookmarks.js" ] } js_library("folder_node") { @@ -216,7 +224,6 @@ js_library("folder_node") { ":util", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] - externs_list = [ "$externs_path/chrome_extensions.js" ] } js_library("item") { @@ -233,7 +240,6 @@ js_library("item") { "//ui/webui/resources/js:icon.m", "//ui/webui/resources/js/cr/ui:focus_without_ink.m", ] - externs_list = [ "$externs_path/chrome_extensions.js" ] } js_library("list") { @@ -281,7 +287,6 @@ js_library("store") { "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js/cr/ui:store.m", ] - externs_list = [ "$externs_path/chrome_extensions.js" ] } js_library("store_client") { @@ -306,18 +311,15 @@ js_library("toolbar") { "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", ] - externs_list = [ - "$externs_path/bookmark_manager_private.js", - "$externs_path/chrome_extensions.js", - ] } js_library("types") { deps = [ ":constants" ] - externs_list = [ "$externs_path/chrome_extensions.js" ] + externs_list = [ "$externs_path/bookmarks.js" ] } js_library("util") { deps = [ ":types" ] - externs_list = [ "$externs_path/chrome_extensions.js" ] + + externs_list = [ "$externs_path/bookmarks.js" ] } diff --git a/chromium/chrome/browser/resources/bookmarks/actions.js b/chromium/chrome/browser/resources/bookmarks/actions.js index 54cfd79207a..a45cd123429 100644 --- a/chromium/chrome/browser/resources/bookmarks/actions.js +++ b/chromium/chrome/browser/resources/bookmarks/actions.js @@ -16,7 +16,7 @@ import {getDescendants, getDisplayedList, normalizeNode} from './util.js'; /** * @param {string} id - * @param {BookmarkTreeNode} treeNode + * @param {chrome.bookmarks.BookmarkTreeNode} treeNode */ export function createBookmark(id, treeNode) { return { diff --git a/chromium/chrome/browser/resources/bookmarks/api_listener.js b/chromium/chrome/browser/resources/bookmarks/api_listener.js index bc6b075f315..13723908914 100644 --- a/chromium/chrome/browser/resources/bookmarks/api_listener.js +++ b/chromium/chrome/browser/resources/bookmarks/api_listener.js @@ -89,7 +89,7 @@ function onBookmarkChanged(id, changeInfo) { /** * @param {string} id - * @param {BookmarkTreeNode} treeNode + * @param {chrome.bookmarks.BookmarkTreeNode} treeNode */ function onBookmarkCreated(id, treeNode) { batchUIUpdates(); diff --git a/chromium/chrome/browser/resources/bookmarks/bookmarks.html b/chromium/chrome/browser/resources/bookmarks/bookmarks.html index 5869e33b5cb..2b1fee2c9f2 100644 --- a/chromium/chrome/browser/resources/bookmarks/bookmarks.html +++ b/chromium/chrome/browser/resources/bookmarks/bookmarks.html @@ -1,6 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" - $i18n{a11yenhanced}> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> <head> <meta charset="utf8"> <base href="chrome://bookmarks"> diff --git a/chromium/chrome/browser/resources/bookmarks/bookmarks_resources_vulcanized.grd b/chromium/chrome/browser/resources/bookmarks/bookmarks_resources_vulcanized.grd index b6881426042..8bca4369677 100644 --- a/chromium/chrome/browser/resources/bookmarks/bookmarks_resources_vulcanized.grd +++ b/chromium/chrome/browser/resources/bookmarks/bookmarks_resources_vulcanized.grd @@ -14,14 +14,12 @@ <includes> <include name="IDR_BOOKMARKS_BOOKMARKS_HTML" file="bookmarks.html" - type="chrome_html" - compress="gzip" /> + type="chrome_html" /> <include name="IDR_BOOKMARKS_BOOKMARKS_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\bookmarks\bookmarks.rollup.js" use_base_dir="false" preprocess="true" - type="chrome_html" - compress="gzip" /> + type="chrome_html" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/bookmarks/command_manager.js b/chromium/chrome/browser/resources/bookmarks/command_manager.js index 0326cdaa772..67e6e6a9645 100644 --- a/chromium/chrome/browser/resources/bookmarks/command_manager.js +++ b/chromium/chrome/browser/resources/bookmarks/command_manager.js @@ -471,8 +471,6 @@ export const CommandManager = Polymer({ if (shortcut.matchesEvent(e) && this.canExecute(command, itemIds)) { this.handle(command, itemIds); - this.recordCommandHistogram_( - itemIds, 'BookmarkManager.CommandExecutedFromKeyboard', command); e.stopPropagation(); e.preventDefault(); return true; diff --git a/chromium/chrome/browser/resources/bookmarks/item.html b/chromium/chrome/browser/resources/bookmarks/item.html index def6e11eb28..f65015195ed 100644 --- a/chromium/chrome/browser/resources/bookmarks/item.html +++ b/chromium/chrome/browser/resources/bookmarks/item.html @@ -15,10 +15,6 @@ background-color: var(--highlight-color); } - :host([is-selected-item_]) cr-icon-button { - --cr-icon-button-fill-color-focus: var(--highlight-color); - } - @media (prefers-color-scheme: dark) { :host([is-selected-item_]), :host([is-selected-item_]) .folder-icon { diff --git a/chromium/chrome/browser/resources/bookmarks/toolbar.html b/chromium/chrome/browser/resources/bookmarks/toolbar.html index 1f85ea820e2..764da792202 100644 --- a/chromium/chrome/browser/resources/bookmarks/toolbar.html +++ b/chromium/chrome/browser/resources/bookmarks/toolbar.html @@ -10,7 +10,6 @@ } cr-icon-button { - --cr-icon-button-fill-color-focus: var(--cr-toolbar-background-color); justify-content: flex-end; margin: 4px; } diff --git a/chromium/chrome/browser/resources/bookmarks/types.js b/chromium/chrome/browser/resources/bookmarks/types.js index 1487eae9fb5..0031ae7c6c7 100644 --- a/chromium/chrome/browser/resources/bookmarks/types.js +++ b/chromium/chrome/browser/resources/bookmarks/types.js @@ -97,7 +97,7 @@ export class BookmarkElement extends HTMLElement { export class DragData { constructor() { - /** @type {Array<BookmarkTreeNode>} */ + /** @type {Array<chrome.bookmarks.BookmarkTreeNode>} */ this.elements = null; /** @type {boolean} */ diff --git a/chromium/chrome/browser/resources/bookmarks/util.js b/chromium/chrome/browser/resources/bookmarks/util.js index cbe9aa0c072..b0e1184e4d4 100644 --- a/chromium/chrome/browser/resources/bookmarks/util.js +++ b/chromium/chrome/browser/resources/bookmarks/util.js @@ -26,7 +26,7 @@ export function getDisplayedList(state) { } /** - * @param {BookmarkTreeNode} treeNode + * @param {chrome.bookmarks.BookmarkTreeNode} treeNode * @return {!BookmarkNode} */ export function normalizeNode(treeNode) { @@ -46,7 +46,7 @@ export function normalizeNode(treeNode) { } /** - * @param {BookmarkTreeNode} rootNode + * @param {chrome.bookmarks.BookmarkTreeNode} rootNode * @return {NodeMap} */ export function normalizeNodes(rootNode) { diff --git a/chromium/chrome/browser/resources/chromeos/BUILD.gn b/chromium/chrome/browser/resources/chromeos/BUILD.gn index d4f57c718a8..675d9ee14d8 100644 --- a/chromium/chrome/browser/resources/chromeos/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/BUILD.gn @@ -34,29 +34,6 @@ grit("multidevice_setup_resources") { output_dir = "$root_gen_dir/chrome" } -grit("camera_resources") { - source = "camera/camera_resources.grd" - - defines = chrome_grit_defines - outputs = [ - "grit/camera_resources.h", - "grit/camera_resources_map.cc", - "grit/camera_resources_map.h", - "camera_resources.pak", - ] - output_dir = "$root_gen_dir/chrome" - - deps = [ - "//components/arc/mojom:camera_intent_js", - "//media/capture/video/chromeos/mojom:cros_camera_js", - ] - - grit_flags = [ - "-E", - "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), - ] -} - group("closure_compile") { deps = [ "accessibility/braille_ime:closure_compile", @@ -64,7 +41,6 @@ group("closure_compile") { "accessibility/switch_access:closure_compile", "add_supervision:closure_compile", "bluetooth_pairing_dialog:closure_compile", - "camera/src/js:closure_compile", "crostini_installer:closure_compile", "edu_login:closure_compile", "emulator:closure_compile", diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/BUILD.gn index 0f4967d66af..31961f1aae2 100644 --- a/chromium/chrome/browser/resources/chromeos/accessibility/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/accessibility/BUILD.gn @@ -21,11 +21,13 @@ group("build") { ] if (is_chromeos) { deps += [ + ":accessibility_common_guest_manifest", + ":accessibility_common_manifest", ":select_to_speak_guest_manifest", ":select_to_speak_manifest", ":switch_access_guest_manifest", ":switch_access_manifest", - "autoclick:build", + "accessibility_common:build", "select_to_speak:build", "switch_access:build", ] @@ -58,6 +60,20 @@ template("manifest") { } } +manifest("accessibility_common_manifest") { + input_file = "accessibility_common_manifest.json.jinja2" + output_file = "$accessibility_out_dir/accessibility_common_manifest.json" + key = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6SX/t6kDEi9UiG4fULwjbEW1uJmQoiJPtxvSZ/SDH14OjSzmfP6xfE97Hus3EY8uSIMxTHkGaZliGbFbIQXQn6/XwBpQRu2gPlrfz7TWR1Hw6SboBBMOpltM9A2nx+d3jLtz+YtKNYVcHyNil9hXfFeyFe6g5kLHapKb1UO0jo3q3kovo1a1z7ujzGwogfLmb58w1hkdFBnnqumRlT55dKLN8AQ6cSdB1sjDVoMgPYeWgkzXr9cR3A8UVJookSO0sDAmD+W8BtBijapt3UVkHiIL1NTPuXvGGUHL7TPFo5WcBXFMkTz74gJqqFdO5hQ2YWXAaCxQJwgJrQPrvPMSJAgMBAAECggEADDhEDww9wWbWzUz3BQEs2In1HrOgAFStN3zEkNFc9B78AJsvpXWczgPUqk9jrg1JzkUeghlK/mDWT8MNkkdQ4kmFMYCM9/jOI6+kU3js+arxlzU84VI5r4c4RhlSOtBEMOHjF0DORP3sopMXOxPAbYjXog3xhA0szYXdedwcIik7Xu3lt1Hl5FfVZbvVLdf4vw0jTfHcp8SmHy/BDVnSCrhC3pnPGi6o+lUaSK0ca3uvcJDZGLXJ/6LyFb6uLlS2XUoBMYsombioRKrerJJSOmMTLHvfu1cM6+iQ+J0wdBnJQpgmDoSVGjnksPU2SMpWgG2OzwuZYIUGI745s19wLQKBgQDvdHsMZ4ttBr9bjydzeZVATWTICHZgXdAYgfgrbGwppYDUjfKoAuJ6bHTvff4nj8aZrY+Y1SwuvqxgHHfiggUgqg+JyeaAdQG+CLdfl1M8An+6H0x/hx0nk0oOJQhu0y1R/SbtnDJ6JASszg/VrTwHIYbzUl6xKHbZ6X41apyLYwKBgQDHKJOeZdxuYj7AsAqFGreuPoAEh0S+2VHHi4rjNz5dC1z7o/8siixfkHg7ONM2hqCKo55XYj4UWtprEFZJ9ohbizHELNzpnTxjdS0cG/VfItml6CDJaUtrkShIx17yGjNi0u/7ywHQ3slJsUXu7CbEcESwEzdoSrsC048dyxBSIwKBgF0141wtxklXcg/LBtldf6q7NbrkCGh0vDd+CEOm/eesRBz5cHbUQKLVKyO60L9HqVBTDm24tW0wzdrP2h7y69oOOOQzEqX4Zgg6Tl9IgZ7/fgbOfjG6P7ATFqWw5rp1O9QJjii6P6/p62P1Bpbvy0kfVO/MpY2iqbkjufxDFtLvAoGBAMC5p4CVGedH82oL8WI1JKLdoIzBSelV7CmqA9E1WIg5wtVRMlIrtB0WdQL6ToppZVpEU6pES8bu1Ibe3GHezL2pyZMJxw3bNuEYN3sIIz7ZPr2qEHBYEMAbTFyBcoPejvOHJO0I2s0BitBhWEeJB0r5Sb8KGYg3KRnnGIvAQh75AoGBANEC/k1umGrnMO3rwHJF7R+aTHzeMnO6oi11pmSnT7eJcF+oi7OwHS3ickU6sGrIb5QmnwCY9ES1qY6mP7N++KQGsdQM2l13MpCn8cBZgrfpQg2slP1dz8LCDW/PB+6MF7qwEHN2afVA2muQaez+q0eXZjMXmGJ3VZIXz/cxBLD6" +} + +manifest("accessibility_common_guest_manifest") { + input_file = "accessibility_common_manifest.json.jinja2" + output_file = + "$accessibility_out_dir/accessibility_common_guest_manifest.json" + key = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6SX/t6kDEi9UiG4fULwjbEW1uJmQoiJPtxvSZ/SDH14OjSzmfP6xfE97Hus3EY8uSIMxTHkGaZliGbFbIQXQn6/XwBpQRu2gPlrfz7TWR1Hw6SboBBMOpltM9A2nx+d3jLtz+YtKNYVcHyNil9hXfFeyFe6g5kLHapKb1UO0jo3q3kovo1a1z7ujzGwogfLmb58w1hkdFBnnqumRlT55dKLN8AQ6cSdB1sjDVoMgPYeWgkzXr9cR3A8UVJookSO0sDAmD+W8BtBijapt3UVkHiIL1NTPuXvGGUHL7TPFo5WcBXFMkTz74gJqqFdO5hQ2YWXAaCxQJwgJrQPrvPMSJAgMBAAECggEADDhEDww9wWbWzUz3BQEs2In1HrOgAFStN3zEkNFc9B78AJsvpXWczgPUqk9jrg1JzkUeghlK/mDWT8MNkkdQ4kmFMYCM9/jOI6+kU3js+arxlzU84VI5r4c4RhlSOtBEMOHjF0DORP3sopMXOxPAbYjXog3xhA0szYXdedwcIik7Xu3lt1Hl5FfVZbvVLdf4vw0jTfHcp8SmHy/BDVnSCrhC3pnPGi6o+lUaSK0ca3uvcJDZGLXJ/6LyFb6uLlS2XUoBMYsombioRKrerJJSOmMTLHvfu1cM6+iQ+J0wdBnJQpgmDoSVGjnksPU2SMpWgG2OzwuZYIUGI745s19wLQKBgQDvdHsMZ4ttBr9bjydzeZVATWTICHZgXdAYgfgrbGwppYDUjfKoAuJ6bHTvff4nj8aZrY+Y1SwuvqxgHHfiggUgqg+JyeaAdQG+CLdfl1M8An+6H0x/hx0nk0oOJQhu0y1R/SbtnDJ6JASszg/VrTwHIYbzUl6xKHbZ6X41apyLYwKBgQDHKJOeZdxuYj7AsAqFGreuPoAEh0S+2VHHi4rjNz5dC1z7o/8siixfkHg7ONM2hqCKo55XYj4UWtprEFZJ9ohbizHELNzpnTxjdS0cG/VfItml6CDJaUtrkShIx17yGjNi0u/7ywHQ3slJsUXu7CbEcESwEzdoSrsC048dyxBSIwKBgF0141wtxklXcg/LBtldf6q7NbrkCGh0vDd+CEOm/eesRBz5cHbUQKLVKyO60L9HqVBTDm24tW0wzdrP2h7y69oOOOQzEqX4Zgg6Tl9IgZ7/fgbOfjG6P7ATFqWw5rp1O9QJjii6P6/p62P1Bpbvy0kfVO/MpY2iqbkjufxDFtLvAoGBAMC5p4CVGedH82oL8WI1JKLdoIzBSelV7CmqA9E1WIg5wtVRMlIrtB0WdQL6ToppZVpEU6pES8bu1Ibe3GHezL2pyZMJxw3bNuEYN3sIIz7ZPr2qEHBYEMAbTFyBcoPejvOHJO0I2s0BitBhWEeJB0r5Sb8KGYg3KRnnGIvAQh75AoGBANEC/k1umGrnMO3rwHJF7R+aTHzeMnO6oi11pmSnT7eJcF+oi7OwHS3ickU6sGrIb5QmnwCY9ES1qY6mP7N++KQGsdQM2l13MpCn8cBZgrfpQg2slP1dz8LCDW/PB+6MF7qwEHN2afVA2muQaez+q0eXZjMXmGJ3VZIXz/cxBLD6" + is_guest_manifest = true +} + manifest("chromevox_manifest") { input_file = "chromevox_manifest.json.jinja2" output_file = "$accessibility_out_dir/chromevox_manifest.json" @@ -105,7 +121,7 @@ group("browser_tests") { testonly = true if (is_chromeos) { deps = [ - "autoclick:browser_tests", + "accessibility_common:browser_tests", "chromevox:browser_tests", "common:browser_tests", "select_to_speak:browser_tests", diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn new file mode 100644 index 00000000000..9cb8ce6e600 --- /dev/null +++ b/chromium/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn @@ -0,0 +1,87 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/features.gni") +import( + "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni") +import("//chrome/test/base/js2gtest.gni") +import("//testing/test.gni") +import("//third_party/closure_compiler/compile_js.gni") + +assert(is_chromeos) + +accessibility_common_dir = + "$root_out_dir/resources/chromeos/accessibility/accessibility_common" + +group("build") { + deps = [ ":accessibility_common_copied_files" ] +} + +# Instead of setting up copy targets, use a script to copy all files. +run_jsbundler("accessibility_common_copied_files") { + mode = "copy" + dest_dir = accessibility_common_dir + sources = [ + "accessibility_common_loader.js", + "autoclick/autoclick.js", + ] + rewrite_rules = [ + rebase_path(".", root_build_dir) + ":", + rebase_path(closure_library_dir, root_build_dir) + ":closure", + ] +} + +source_set("browser_tests") { + testonly = true + assert(enable_extensions) + + deps = [ ":accessibility_common_extjs_tests" ] + + data = [ + "$root_out_dir/chrome_100_percent.pak", + "$root_out_dir/chrome_200_percent.pak", + "$root_out_dir/locales/en-US.pak", + "$root_out_dir/resources.pak", + "$root_out_dir/resources/chromeos/accessibility/accessibility_common/", + "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/accessibility_common/", + + # The test uses data from the original location, not the copied one. + "//chrome/browser/resources/chromeos/accessibility/accessibility_common/", + "//chrome/browser/resources/chromeos/accessibility/common/", + "//ui/webui/resources/js/cr.js", + ] + data += js2gtest_js_libraries +} + +js2gtest("accessibility_common_extjs_tests") { + test_type = "extension" + sources = [ "autoclick_test.js" ] + gen_include_files = [ + "../common/testing/callback_helper.js", + "mock_accessibility_private.js", + ] + + # The test base classes generate C++ code with these deps. + deps = [ + "//ash", + "//ash/keyboard/ui", + "//base", + "//chrome/browser/chromeos", + "//chrome/common", + ] + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] +} + +js_type_check("closure_compile") { + deps = [ ":accessibility_common" ] +} + +js_library("accessibility_common") { + deps = [] + externs_list = [ + "$externs_path/accessibility_private.js", + "$externs_path/automation.js", + "$externs_path/accessibility_features.js", + ] +} diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/autoclick/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/autoclick/BUILD.gn deleted file mode 100644 index f4cc2e8b078..00000000000 --- a/chromium/chrome/browser/resources/chromeos/accessibility/autoclick/BUILD.gn +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/features.gni") -import( - "//chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni") -import("//chrome/test/base/js2gtest.gni") -import("//testing/test.gni") -import("//third_party/closure_compiler/compile_js.gni") - -assert(is_chromeos) - -autoclick_dir = "$root_out_dir/resources/chromeos/accessibility/autoclick" - -group("build") { - deps = [ - ":autoclick_copied_files", - ":autoclick_guest_manifest", - ":autoclick_manifest", - ] -} - -# Instead of setting up copy targets, use a script to copy all files. -run_jsbundler("autoclick_copied_files") { - mode = "copy" - dest_dir = autoclick_dir - sources = [ "autoclick.js" ] - rewrite_rules = [ - rebase_path(".", root_build_dir) + ":", - rebase_path(closure_library_dir, root_build_dir) + ":closure", - ] -} - -# TODO(crbug/978200): refactor this into another file like generate_manifest.gni -# to share with other extensions. -template("manifest") { - version_file = "//chrome/VERSION" - version_script = "//build/util/version.py" - template_file = "manifest.json.jinja2" - output_file = invoker.output_file - key = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6SX/t6kDEi9UiG4fULwjbEW1uJmQoiJPtxvSZ/SDH14OjSzmfP6xfE97Hus3EY8uSIMxTHkGaZliGbFbIQXQn6/XwBpQRu2gPlrfz7TWR1Hw6SboBBMOpltM9A2nx+d3jLtz+YtKNYVcHyNil9hXfFeyFe6g5kLHapKb1UO0jo3q3kovo1a1z7ujzGwogfLmb58w1hkdFBnnqumRlT55dKLN8AQ6cSdB1sjDVoMgPYeWgkzXr9cR3A8UVJookSO0sDAmD+W8BtBijapt3UVkHiIL1NTPuXvGGUHL7TPFo5WcBXFMkTz74gJqqFdO5hQ2YWXAaCxQJwgJrQPrvPMSJAgMBAAECggEADDhEDww9wWbWzUz3BQEs2In1HrOgAFStN3zEkNFc9B78AJsvpXWczgPUqk9jrg1JzkUeghlK/mDWT8MNkkdQ4kmFMYCM9/jOI6+kU3js+arxlzU84VI5r4c4RhlSOtBEMOHjF0DORP3sopMXOxPAbYjXog3xhA0szYXdedwcIik7Xu3lt1Hl5FfVZbvVLdf4vw0jTfHcp8SmHy/BDVnSCrhC3pnPGi6o+lUaSK0ca3uvcJDZGLXJ/6LyFb6uLlS2XUoBMYsombioRKrerJJSOmMTLHvfu1cM6+iQ+J0wdBnJQpgmDoSVGjnksPU2SMpWgG2OzwuZYIUGI745s19wLQKBgQDvdHsMZ4ttBr9bjydzeZVATWTICHZgXdAYgfgrbGwppYDUjfKoAuJ6bHTvff4nj8aZrY+Y1SwuvqxgHHfiggUgqg+JyeaAdQG+CLdfl1M8An+6H0x/hx0nk0oOJQhu0y1R/SbtnDJ6JASszg/VrTwHIYbzUl6xKHbZ6X41apyLYwKBgQDHKJOeZdxuYj7AsAqFGreuPoAEh0S+2VHHi4rjNz5dC1z7o/8siixfkHg7ONM2hqCKo55XYj4UWtprEFZJ9ohbizHELNzpnTxjdS0cG/VfItml6CDJaUtrkShIx17yGjNi0u/7ywHQ3slJsUXu7CbEcESwEzdoSrsC048dyxBSIwKBgF0141wtxklXcg/LBtldf6q7NbrkCGh0vDd+CEOm/eesRBz5cHbUQKLVKyO60L9HqVBTDm24tW0wzdrP2h7y69oOOOQzEqX4Zgg6Tl9IgZ7/fgbOfjG6P7ATFqWw5rp1O9QJjii6P6/p62P1Bpbvy0kfVO/MpY2iqbkjufxDFtLvAoGBAMC5p4CVGedH82oL8WI1JKLdoIzBSelV7CmqA9E1WIg5wtVRMlIrtB0WdQL6ToppZVpEU6pES8bu1Ibe3GHezL2pyZMJxw3bNuEYN3sIIz7ZPr2qEHBYEMAbTFyBcoPejvOHJO0I2s0BitBhWEeJB0r5Sb8KGYg3KRnnGIvAQh75AoGBANEC/k1umGrnMO3rwHJF7R+aTHzeMnO6oi11pmSnT7eJcF+oi7OwHS3ickU6sGrIb5QmnwCY9ES1qY6mP7N++KQGsdQM2l13MpCn8cBZgrfpQg2slP1dz8LCDW/PB+6MF7qwEHN2afVA2muQaez+q0eXZjMXmGJ3VZIXz/cxBLD6" - action(target_name) { - script = "//chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_manifest.py" - inputs = [ - version_file, - version_script, - ] - sources = [ template_file ] - outputs = [ output_file ] - args = [ - "--key=$key", - "--version_file=" + rebase_path(version_file, root_build_dir), - "--output_manifest=" + rebase_path(output_file, root_build_dir), - ] - if (defined(invoker.is_guest_manifest) && invoker.is_guest_manifest) { - args += [ "--is_guest_manifest=1" ] - } - args += rebase_path(sources, root_build_dir) - } -} - -manifest("autoclick_manifest") { - output_file = "$autoclick_dir/manifest.json" -} - -manifest("autoclick_guest_manifest") { - output_file = "$autoclick_dir/manifest_guest.json" - is_guest_manifest = true -} - -source_set("browser_tests") { - testonly = true - assert(enable_extensions) - - deps = [ ":autoclick_extjs_tests" ] - - data = [ - "$root_out_dir/chrome_100_percent.pak", - "$root_out_dir/chrome_200_percent.pak", - "$root_out_dir/locales/en-US.pak", - "$root_out_dir/resources.pak", - "$root_out_dir/resources/chromeos/accessibility/autoclick/", - "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/autoclick/", - - # The test uses data from the original location, not the copied one. - "//chrome/browser/resources/chromeos/accessibility/autoclick/", - "//chrome/browser/resources/chromeos/accessibility/chromevox/", - "//ui/webui/resources/js/cr.js", - ] - data += js2gtest_js_libraries -} - -js2gtest("autoclick_extjs_tests") { - test_type = "extension" - sources = [ "autoclick_test.js" ] - gen_include_files = [ - "../chromevox/testing/callback_helper.js", - "mock_accessibility_private.js", - ] - - # The test base classes generate C++ code with these deps. - deps = [ - "//ash", - "//ash/keyboard/ui", - "//base", - "//chrome/browser/chromeos", - "//chrome/common", - ] - defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] -} - -js_type_check("closure_compile") { - deps = [ ":autoclick" ] -} - -js_library("autoclick") { - deps = [] - externs_list = [ - "$externs_path/accessibility_private.js", - "$externs_path/automation.js", - ] -} diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index 7d16612e2df..4b6d105774b 100644 --- a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn @@ -3,11 +3,15 @@ # found in the LICENSE file. import("//build/config/features.gni") +import( + "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni") import("//chrome/common/features.gni") import("//chrome/test/base/js2gtest.gni") import("//testing/test.gni") import("//third_party/closure_compiler/compile_js.gni") -import("run_jsbundler.gni") + +# Prevent Chromium source assignment filters from being inherited. +set_sources_assignment_filter([]) declare_args() { # Whether to compress the main Chromevox javascript files or load the @@ -135,12 +139,17 @@ relative_closure_library_modules = [ closure_library_modules = rebase_path(relative_closure_library_modules, ".", closure_library_dir) +chromevox_gen_dir = + "$root_gen_dir/chrome/browser/resources/chromeos/accessibility/chromevox" + chromevox_out_dir = "$root_out_dir/resources/chromeos/accessibility/chromevox" group("build") { deps = [ ":chromevox_copied_files", ":chromevox_phonetic_dictionaries_js", + ":lesson_component", + ":tutorial_component", "//chrome/browser/resources/chromeos/accessibility/braille_ime:braille_ime_manifest", "//third_party/chromevox:chromevox_third_party_resources", "//third_party/liblouis", @@ -182,6 +191,11 @@ run_jsbundler("chromevox_copied_files") { "background/keymaps/default_keymap.json", "background/logging/log.css", "background/logging/log.html", + "i_tutorial/components/i_tutorial.js", + "i_tutorial/components/tutorial_lesson.js", + "i_tutorial/lessons/basic_navigation.html", + "i_tutorial/lessons/jump_commands.html", + "i_tutorial/lessons/text_fields.html", "images/chromevox-128.png", "images/chromevox-16.png", "images/chromevox-19.png", @@ -387,8 +401,8 @@ if (is_chromeos) { "testing/mock_feedback_test.js", ] gen_include_files = [ - "testing/assert_additions.js", - "testing/callback_helper.js", + "../common/testing/assert_additions.js", + "../common/testing/callback_helper.js", "testing/chromevox_unittest_base.js", "testing/mock_feedback.js", ] @@ -426,8 +440,8 @@ if (is_chromeos) { "panel/panel_test.js", ] gen_include_files = [ - "testing/assert_additions.js", - "testing/callback_helper.js", + "../common/testing/assert_additions.js", + "../common/testing/callback_helper.js", "testing/chromevox_e2e_test_base.js", "testing/chromevox_next_e2e_test_base.js", "testing/mock_feedback.js", @@ -443,3 +457,22 @@ if (is_chromeos) { defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] } } + +copy("lesson_component") { + sources = [ "$chromevox_gen_dir/i_tutorial/components/tutorial_lesson.js" ] + outputs = [ "$chromevox_out_dir/i_tutorial/tutorial_lesson.js" ] + deps = [ + "i_tutorial/components:closure_compile", + "i_tutorial/components:components", + ] +} + +copy("tutorial_component") { + sources = [ "$chromevox_gen_dir/i_tutorial/components/i_tutorial.js" ] + outputs = [ "$chromevox_out_dir/i_tutorial/i_tutorial.js" ] + + deps = [ + "i_tutorial/components:closure_compile", + "i_tutorial/components:components", + ] +} diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/BUILD.gn new file mode 100644 index 00000000000..679a3871583 --- /dev/null +++ b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/BUILD.gn @@ -0,0 +1,33 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +html_to_js("components") { + js_files = [ + "tutorial_lesson.js", + "i_tutorial.js", + ] +} + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ + ":i_tutorial", + ":tutorial_lesson", + ] +} + +js_library("tutorial_lesson") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} + +js_library("i_tutorial") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn index 8f6bb71d6e2..af38f4fb21f 100644 --- a/chromium/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn @@ -4,7 +4,7 @@ import("//build/config/features.gni") import( - "//chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni") + "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni") import("//chrome/common/features.gni") import("//chrome/test/base/js2gtest.gni") import("//testing/test.gni") @@ -29,6 +29,7 @@ run_jsbundler("accessibility_common_copied_files") { "automation_util.js", "closure_shim.js", "constants.js", + "repeated_event_handler.js", "tree_walker.js", ] rewrite_rules = [ rebase_path(".", root_build_dir) + ":" ] @@ -78,6 +79,10 @@ js_library("automation_util") { ] } +js_library("repeated_event_handler") { + externs_list = [ "$externs_path/automation.js" ] +} + source_set("browser_tests") { testonly = true assert(enable_extensions) @@ -108,15 +113,16 @@ js2gtest("accessibility_tests") { sources = [ "array_util_test.js", "automation_util_test.js", + "repeated_event_handler_test.js", "tree_walker_test.js", ] gen_include_files = [ - "../chromevox/testing/assert_additions.js", - "../chromevox/testing/callback_helper.js", "../chromevox/testing/chromevox_e2e_test_base.js", "../chromevox/testing/chromevox_next_e2e_test_base.js", "../chromevox/testing/mock_feedback.js", "array_util.js", + "testing/assert_additions.js", + "testing/callback_helper.js", ] if (is_chromeos) { diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni b/chromium/chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni index c68bb6df6fa..c68bb6df6fa 100644 --- a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni +++ b/chromium/chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn index e2cf38296ad..63356e98621 100644 --- a/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn @@ -4,7 +4,7 @@ import("//build/config/features.gni") import( - "//chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni") + "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni") import("//chrome/common/features.gni") import("//chrome/test/base/js2gtest.gni") import("//testing/test.gni") @@ -65,7 +65,7 @@ source_set("browser_tests") { "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/select_to_speak/", # The test uses data from the original location, not the copied one. - "//chrome/browser/resources/chromeos/accessibility/chromevox/", + "//chrome/browser/resources/chromeos/accessibility/common/", "//chrome/browser/resources/chromeos/accessibility/select_to_speak/", "//ui/webui/resources/js/cr.js", ] @@ -80,7 +80,7 @@ js2gtest("select_to_speak_extjs_tests") { "select_to_speak_prefs_test.js", ] gen_include_files = [ - "../chromevox/testing/callback_helper.js", + "../common/testing/callback_helper.js", "mock_storage.js", "mock_tts.js", "select_to_speak_e2e_test_base.js", diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp b/chromium/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp index 75c816257cb..c7bf4b862b0 100644 --- a/chromium/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp +++ b/chromium/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp @@ -380,7 +380,10 @@ Show Log </message> <message desc="Keyboard shortcut to show the ChromeVox log." name="IDS_CHROMEVOX_OPTIONS_SHOW_LOG_KEY"> - Search + O + W + Search + O, then W + </message> + <message desc="Keyboard shortcut to show the TTS settings page." name="IDS_CHROMEVOX_OPTIONS_SHOW_TTS_SETTINGS"> + Search + O, then S. Use to install, manage, and customize voices. </message> <message desc="Show event stream filters options for event stream logging." name="IDS_CHROMEVOX_OPTIONS_SHOW_EVENT_STREAM_FILTERS"> Show event stream filters @@ -2975,5 +2978,8 @@ <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_CLICK_GESTURE"> Double tap with one finger </message> + <message desc="The text label for the use pitch changes checkbox." name="IDS_CHROMEVOX_OPTIONS_USE_PITCH_CHANGES_CHECKBOX_LABEL"> + Change pitch when speaking element types and quoted, deleted, bolded, parenthesized, or capitalized text. + </message> </grit-part> diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp b/chromium/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp index fa31306e16b..58a65969ce8 100644 --- a/chromium/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp +++ b/chromium/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp @@ -45,6 +45,9 @@ <message desc="Example of a word highlight on a light background in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_LIGHT"> Light background </message> +<message desc="Label for option to fade the background outside of the focus ring to improve focus on what is being spoken." name="IDS_SELECT_TO_SPEAK_OPTIONS_BACKGROUND_SHADING_DESCRIPTION"> + Shade background content +</message> <message desc="Link to the Text-to-Speech settings page." name="IDS_SELECT_TO_SPEAK_OPTIONS_TEXT_TO_SPEECH_SETTINGS"> Personalize Text-to-Speech settings </message> @@ -72,4 +75,7 @@ <message desc="Description of a radio button that is selected" name="IDS_SELECT_TO_SPEAK_RADIOBUTTON_MIXED"> partially selected </message> +<message desc="Sample text around which will be drawn a Select to Speak visual preview. This should be less than one line long." name="IDS_SELECT_TO_SPEAK_OPTIONS_SAMPLE_TEXT"> + The quick brown fox jumped over the lazy dog. +</message> </grit-part> diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn index b930b96e57d..8f75b17ff43 100644 --- a/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn @@ -4,7 +4,7 @@ import("//build/config/features.gni") import( - "//chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni") + "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni") import("//chrome/common/features.gni") import("//chrome/test/base/js2gtest.gni") import("//testing/test.gni") @@ -58,21 +58,20 @@ run_jsbundler("switch_access_copied_files") { "icons/textSelectionEnd.svg", "icons/textSelectionStart.svg", "menu_manager.js", - "menu_panel.css", - "menu_panel.html", - "menu_panel.js", - "menu_panel_interface.js", "metrics.js", "navigation_manager.js", "nodes/back_button_node.js", + "nodes/combo_box_node.js", "nodes/desktop_node.js", "nodes/editable_text_node.js", "nodes/group_node.js", "nodes/keyboard_node.js", + "nodes/modal_dialog_node.js", "nodes/node_wrapper.js", + "nodes/slider_node.js", "nodes/switch_access_node.js", - "nodes/system_menu_node.js", "nodes/tab_node.js", + "nodes/window_node.js", "preferences.js", "rect_helper.js", "switch_access.js", @@ -93,7 +92,7 @@ source_set("browser_tests") { deps = [ ":switch_access_extjs_tests" ] data = [ - "//chrome/browser/resources/chromeos/accessibility/chromevox/", + "//chrome/browser/resources/chromeos/accessibility/common/", "//chrome/browser/resources/chromeos/accessibility/switch_access/", "//ui/webui/resources/js/cr.js", ] @@ -112,7 +111,8 @@ js2gtest("switch_access_extjs_tests") { "text_navigation_manager_test.js", ] gen_include_files = [ - "../chromevox/testing/callback_helper.js", + "../common/testing/assert_additions.js", + "../common/testing/callback_helper.js", "switch_access_e2e_test_base.js", ] @@ -133,6 +133,7 @@ js_type_check("closure_compile") { ":auto_scan_manager", ":back_button_node", ":background", + ":combo_box_node", ":commands", ":desktop_node", ":editable_text_node", @@ -142,22 +143,24 @@ js_type_check("closure_compile") { ":history", ":keyboard_node", ":menu_manager", - ":menu_panel", - ":menu_panel_interface", ":metrics", + ":modal_dialog_node", ":navigation_manager", ":node_wrapper", ":preferences", ":rect_helper", + ":slider_node", ":switch_access", ":switch_access_constants", ":switch_access_node", ":switch_access_predicate", - ":system_menu_node", ":tab_node", ":text_navigation_manager", + ":window_node", + "../common:automation_predicate", "../common:closure_shim", "../common:constants", + "../common:repeated_event_handler", "../common:tree_walker", ] } @@ -184,7 +187,22 @@ js_library("back_button_node") { ] } +js_library("combo_box_node") { + sources = [ "nodes/combo_box_node.js" ] + deps = [ + ":event_helper", + ":node_wrapper", + ":switch_access_constants", + ] + externs_list = [] +} + js_library("commands") { + deps = [ + ":auto_scan_manager", + ":menu_manager", + ":navigation_manager", + ] externs_list = [ "$externs_path/accessibility_private.js" ] } @@ -213,8 +231,8 @@ js_library("event_helper") { js_library("focus_ring_manager") { deps = [ - ":menu_panel_interface", ":node_wrapper", + ":switch_access_constants", ":switch_access_node", ] externs_list = [ "$externs_path/accessibility_private.js" ] @@ -266,54 +284,46 @@ js_library("keyboard_node") { js_library("menu_manager") { deps = [ - ":event_helper", - ":menu_panel_interface", - ":metrics", - ":node_wrapper", - ":rect_helper", ":switch_access_constants", ":switch_access_node", - ":switch_access_predicate", - ":text_navigation_manager", - "../common:constants", - "../common:tree_walker", + "../common:array_util", ] externs_list = [ "$externs_path/accessibility_private.js", "$externs_path/automation.js", - "$externs_path/clipboard.js", ] } -js_library("menu_panel") { - deps = [ - ":menu_manager", - ":switch_access_constants", - ] - externs_list = [ "$externs_path/chrome_extensions.js" ] -} - -js_library("menu_panel_interface") { -} - js_library("metrics") { deps = [ ":switch_access_constants" ] externs_list = [ "$externs_path/metrics_private.js" ] } +js_library("modal_dialog_node") { + sources = [ "nodes/modal_dialog_node.js" ] + deps = [ + ":event_helper", + ":node_wrapper", + ":switch_access_constants", + ":switch_access_node", + ] + externs_list = [ "$externs_path/automation.js" ] +} + js_library("navigation_manager") { deps = [ ":desktop_node", ":focus_ring_manager", + ":history", ":keyboard_node", ":menu_manager", - ":menu_panel_interface", ":metrics", + ":modal_dialog_node", ":node_wrapper", ":switch_access_constants", ":switch_access_node", ":switch_access_predicate", - ":system_menu_node", + "../common:repeated_event_handler", ] externs_list = [ "$externs_path/accessibility_private.js", @@ -328,7 +338,9 @@ js_library("node_wrapper") { ":switch_access_constants", ":switch_access_node", ":switch_access_predicate", + "../common:automation_predicate", "../common:constants", + "../common:repeated_event_handler", "../common:tree_walker", ] externs_list = [ @@ -346,12 +358,21 @@ js_library("rect_helper") { externs_list = [ "$externs_path/accessibility_private.js" ] } +js_library("slider_node") { + sources = [ "nodes/slider_node.js" ] + deps = [ + ":event_helper", + ":node_wrapper", + ":switch_access_constants", + ] + externs_list = [ "$externs_path/automation.js" ] +} + js_library("switch_access") { deps = [ ":auto_scan_manager", ":commands", ":menu_manager", - ":menu_panel_interface", ":navigation_manager", ":preferences", ":switch_access_constants", @@ -362,6 +383,7 @@ js_library("switch_access") { "$externs_path/automation.js", "$externs_path/command_line_private.js", "$externs_path/metrics_private.js", + "$externs_path/virtual_keyboard_private.js", ] } @@ -381,17 +403,7 @@ js_library("switch_access_predicate") { deps = [ ":switch_access_constants", ":switch_access_node", - ] - externs_list = [ "$externs_path/automation.js" ] -} - -js_library("system_menu_node") { - sources = [ "nodes/system_menu_node.js" ] - deps = [ - ":event_helper", - ":node_wrapper", - ":switch_access_constants", - ":switch_access_node", + "../common:automation_predicate", ] externs_list = [ "$externs_path/automation.js" ] } @@ -412,5 +424,16 @@ js_library("text_navigation_manager") { externs_list = [ "$externs_path/accessibility_private.js", "$externs_path/automation.js", + "$externs_path/clipboard.js", ] } + +js_library("window_node") { + sources = [ "nodes/window_node.js" ] + deps = [ + ":node_wrapper", + ":switch_access_constants", + ":switch_access_node", + ] + externs_list = [ "$externs_path/automation.js" ] +} diff --git a/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn b/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn index e7e7cc85086..f0bd4bdd7bc 100644 --- a/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn @@ -2,36 +2,77 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//chrome/common/features.gni") import("//third_party/closure_compiler/compile_js.gni") +import("//tools/grit/grit_rule.gni") +import("//tools/polymer/html_to_js.gni") +import("//tools/polymer/polymer.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") import("../../optimize_webui.gni") -optimize_webui("build") { - host = "bluetooth_pairing_dialog" - html_in_files = [ "bluetooth_pairing_dialog.html" ] - html_out_files = [ "vulcanized.html" ] +if (optimize_webui) { + bluetooth_dialog_pak_file = "bluetooth_pairing_dialog_resources.pak" + unpak_folder = "bluetooth_pairing_dialog_resources.unpak" - input = rebase_path(".", root_build_dir) - js_out_files = [ "crisper.js" ] + optimize_webui("build") { + host = "bluetooth-pairing" + js_out_files = [ "bluetooth_pairing_dialog.rollup.js" ] + js_module_in_files = [ "bluetooth_pairing_dialog.js" ] + input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir) - deps = [] + deps = [ + ":unpak", + "../../../../../ui/webui/resources:modulize", + ] + } + + unpak("unpak") { + pak_file = bluetooth_dialog_pak_file + out_folder = unpak_folder + + deps = [ ":flattened_resources" ] + } + + grit("flattened_resources") { + source = "bluetooth_pairing_dialog_resources.grd" + + deps = [ ":web_components" ] + defines = chrome_grit_defines + grit_flags = [ + "-E", + "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), + ] + outputs = [ + "grit/bluetooth_pairing_dialog_resources.h", + "grit/bluetooth_pairing_dialog_resources_map.cc", + "grit/bluetooth_pairing_dialog_resources_map.h", + bluetooth_dialog_pak_file, + ] + output_dir = "$root_gen_dir/chrome/browser/resources/chromeos/bluetooth_pairing_dialog" + } } js_type_check("closure_compile") { + is_polymer3 = true deps = [ ":bluetooth_pairing_dialog" ] } js_library("bluetooth_pairing_dialog") { deps = [ - "//ui/webui/resources/cr_components/chromeos:bluetooth_dialog", - "//ui/webui/resources/js:cr", - "//ui/webui/resources/js:i18n_behavior", - ] - externs_list = [ - "$externs_path/bluetooth.js", - "$externs_path/bluetooth_private.js", + "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_dialog.m", + "//ui/webui/resources/js:cr.m", + "//ui/webui/resources/js:i18n_behavior.m", ] + externs_list = chrome_extension_public_externs + [ + "$externs_path/bluetooth.js", + "$externs_path/bluetooth_private.js", + ] extra_sources = [ "$interfaces_path/bluetooth_interface.js", "$interfaces_path/bluetooth_private_interface.js", ] } + +html_to_js("web_components") { + js_files = [ "bluetooth_pairing_dialog.js" ] +} diff --git a/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd b/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd new file mode 100644 index 00000000000..c345ebb020f --- /dev/null +++ b/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources.grd @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/bluetooth_pairing_dialog_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/bluetooth_pairing_dialog_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/bluetooth_pairing_dialog_resources_map.h" + type="resource_map_header" /> + <output filename="bluetooth_pairing_dialog_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <include name="IDR_BLUETOOTH_PAIRING_DIALOG_JS" + file="${root_gen_dir}/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.js" + use_base_dir="false" + compress="false" + type="chrome_html" /> + </includes> + <structures> + <structure name="IDR_BLUETOOTH_PAIRING_DIALOG_CONTAINER_HTML" + file="bluetooth_pairing_dialog_container.html" + compress="false" + type="chrome_html" /> + </structures> + </release> +</grit>
\ No newline at end of file diff --git a/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources_vulcanized.grd b/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources_vulcanized.grd new file mode 100644 index 00000000000..8816618f277 --- /dev/null +++ b/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog_resources_vulcanized.grd @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/bluetooth_pairing_dialog_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/bluetooth_pairing_dialog_resources_map.cc" + type="resource_map_source" /> + <output filename="grit/bluetooth_pairing_dialog_resources_map.h" + type="resource_map_header" /> + <output filename="bluetooth_pairing_dialog_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <include name="IDR_BLUETOOTH_PAIRING_DIALOG_CONTAINER_HTML" + file="bluetooth_pairing_dialog_container.html" + type="chrome_html" /> + <include name="IDR_BLUETOOTH_PAIRING_DIALOG_ROLLUP_JS" + file="${root_gen_dir}\chrome\browser\resources\chromeos\bluetooth_pairing_dialog\bluetooth_pairing_dialog.rollup.js" + use_base_dir="false" + preprocess="true" + type="chrome_html" /> + </includes> + </release> +</grit> diff --git a/chromium/chrome/browser/resources/chromeos/camera/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/BUILD.gn deleted file mode 100644 index 2c90301b56a..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/BUILD.gn +++ /dev/null @@ -1,252 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -chrome_camera_app_dir = "$root_out_dir/resources/chromeos/camera" - -group("closure_compile") { - deps = [ "src/js:closure_compile" ] -} - -group("chrome_camera_app") { - # According to crbug.com/855747, we should list all the files we want to copy - # rather than list only the folders to avoid potential building issue and ease - # the difficulty to diagnose. - deps = [ - "//chrome/browser/resources/chromeos/camera/src/strings:camera_strings", - ] - - data_deps = [ - ":chrome_camera_app_base", - ":chrome_camera_app_css", - ":chrome_camera_app_images", - ":chrome_camera_app_js", - ":chrome_camera_app_js_browser_proxy", - ":chrome_camera_app_js_device", - ":chrome_camera_app_js_lib", - ":chrome_camera_app_js_models", - ":chrome_camera_app_js_mojo", - ":chrome_camera_app_js_views", - ":chrome_camera_app_js_views_camera", - ":chrome_camera_app_mojo_generated", - ":chrome_camera_app_sounds", - ":chrome_camera_app_views", - ] -} - -copy("chrome_camera_app_base") { - sources = [ "src/manifest.json" ] - - outputs = [ "$chrome_camera_app_dir/{{source_file_part}}" ] -} - -copy("chrome_camera_app_css") { - sources = [ "src/css/main.css" ] - - outputs = [ "$chrome_camera_app_dir/css/{{source_file_part}}" ] -} - -copy("chrome_camera_app_images") { - sources = [ - "src/images/camera_app_icons_128.png", - "src/images/camera_app_icons_48.png", - "src/images/camera_button_fps_30.svg", - "src/images/camera_button_fps_60.svg", - "src/images/camera_button_grid_off.svg", - "src/images/camera_button_grid_on.svg", - "src/images/camera_button_mic_off.svg", - "src/images/camera_button_mic_on.svg", - "src/images/camera_button_mirror_off.svg", - "src/images/camera_button_mirror_on.svg", - "src/images/camera_button_settings.svg", - "src/images/camera_button_switch_device.svg", - "src/images/camera_button_switch_photo.svg", - "src/images/camera_button_switch_video.svg", - "src/images/camera_button_timer_off.svg", - "src/images/camera_button_timer_on_10s.svg", - "src/images/camera_button_timer_on_3s.svg", - "src/images/camera_focus_aim.svg", - "src/images/camera_intent_play_video.svg", - "src/images/camera_intent_result_cancel.svg", - "src/images/camera_intent_result_confirm.svg", - "src/images/camera_mode_photo.svg", - "src/images/camera_mode_portrait.svg", - "src/images/camera_mode_square.svg", - "src/images/camera_mode_video.svg", - "src/images/camera_shutter_photo_start.svg", - "src/images/camera_shutter_photo_start_active.svg", - "src/images/camera_shutter_photo_start_hover.svg", - "src/images/camera_shutter_photo_stop.svg", - "src/images/camera_shutter_photo_stop_hover.svg", - "src/images/settings_button_back.svg", - "src/images/settings_button_expand.svg", - "src/images/settings_feedback.svg", - "src/images/settings_grid_type.svg", - "src/images/settings_help.svg", - "src/images/settings_resolution.svg", - "src/images/settings_timer_duration.svg", - "src/images/spinner.svg", - ] - - outputs = [ "$chrome_camera_app_dir/images/{{source_file_part}}" ] -} - -copy("chrome_camera_app_js") { - sources = [ - "src/js/background.js", - "src/js/background_ops.js", - "src/js/chrome_util.js", - "src/js/error.js", - "src/js/gallerybutton.js", - "src/js/intent.js", - "src/js/main.js", - "src/js/metrics.js", - "src/js/nav.js", - "src/js/perf.js", - "src/js/sound.js", - "src/js/state.js", - "src/js/toast.js", - "src/js/tooltip.js", - "src/js/type.js", - "src/js/util.js", - ] - - outputs = [ "$chrome_camera_app_dir/js/{{source_file_part}}" ] -} - -copy("chrome_camera_app_js_browser_proxy") { - sources = [ - # TODO(b/129956426): Remove dependency used only in closure compiler check. - "src/js/browser_proxy/browser_proxy.js", - "src/js/browser_proxy/browser_proxy_interface.js", - ] - - outputs = [ "$chrome_camera_app_dir/js/browser_proxy/{{source_file_part}}" ] -} - -copy("chrome_camera_app_js_device") { - sources = [ - "src/js/device/camera3_device_info.js", - "src/js/device/constraints_preferrer.js", - "src/js/device/device_info_updater.js", - "src/js/device/error.js", - ] - - outputs = [ "$chrome_camera_app_dir/js/device/{{source_file_part}}" ] -} - -copy("chrome_camera_app_js_lib") { - sources = [ - "src/js/lib/analytics.js", - "src/js/lib/comlink.js", - "src/js/lib/ffmpeg.js", - "src/js/lib/ffmpeg.wasm", - ] - - outputs = [ "$chrome_camera_app_dir/js/lib/{{source_file_part}}" ] -} - -copy("chrome_camera_app_js_models") { - sources = [ - "src/js/models/async_writer.js", - "src/js/models/filenamer.js", - "src/js/models/filesystem.js", - "src/js/models/mp4_video_processor.js", - "src/js/models/nop_video_processor.js", - "src/js/models/result_saver.js", - "src/js/models/video_saver.js", - "src/js/models/waitable_event.js", - ] - - outputs = [ "$chrome_camera_app_dir/js/models/{{source_file_part}}" ] -} - -copy("chrome_camera_app_js_mojo") { - sources = [ - "src/js/mojo/chrome_helper.js", - "src/js/mojo/device_operator.js", - "src/js/mojo/image_capture.js", - ] - - outputs = [ "$chrome_camera_app_dir/js/mojo/{{source_file_part}}" ] -} - -copy("chrome_camera_app_js_views") { - sources = [ - "src/js/views/camera.js", - "src/js/views/camera_intent.js", - "src/js/views/dialog.js", - "src/js/views/settings.js", - "src/js/views/view.js", - "src/js/views/warning.js", - ] - - outputs = [ "$chrome_camera_app_dir/js/views/{{source_file_part}}" ] -} - -copy("chrome_camera_app_js_views_camera") { - sources = [ - "src/js/views/camera/layout.js", - "src/js/views/camera/modes.js", - "src/js/views/camera/options.js", - "src/js/views/camera/preview.js", - "src/js/views/camera/recordtime.js", - "src/js/views/camera/review_result.js", - "src/js/views/camera/timertick.js", - ] - - outputs = [ "$chrome_camera_app_dir/js/views/camera/{{source_file_part}}" ] -} - -copy("chrome_camera_app_sounds") { - sources = [ - "src/sounds/record_end.ogg", - "src/sounds/record_start.ogg", - "src/sounds/shutter.ogg", - "src/sounds/tick_final.ogg", - "src/sounds/tick_inc.ogg", - "src/sounds/tick_start.ogg", - ] - - outputs = [ "$chrome_camera_app_dir/sounds/{{source_file_part}}" ] -} - -copy("chrome_camera_app_views") { - sources = [ - "src/views/background.html", - "src/views/main.html", - ] - - outputs = [ "$chrome_camera_app_dir/views/{{source_file_part}}" ] -} - -copy("chrome_camera_app_mojo_generated") { - sources = [ - "$root_gen_dir/components/arc/mojom/camera_intent.mojom-lite.js", - "$root_gen_dir/components/chromeos_camera/common/camera_app_helper.mojom-lite.js", - "$root_gen_dir/media/capture/mojom/image_capture.mojom-lite.js", - "$root_gen_dir/media/capture/video/chromeos/mojom/camera_app.mojom-lite.js", - "$root_gen_dir/media/capture/video/chromeos/mojom/camera_common.mojom-lite.js", - "$root_gen_dir/media/capture/video/chromeos/mojom/camera_metadata.mojom-lite.js", - "$root_gen_dir/media/capture/video/chromeos/mojom/camera_metadata_tags.mojom-lite.js", - "$root_gen_dir/mojo/public/js/mojo_bindings_lite.js", - "$root_gen_dir/mojo/public/mojom/base/time.mojom-lite.js", - "$root_gen_dir/third_party/blink/public/mojom/idle/idle_manager.mojom-lite.js", - "$root_gen_dir/ui/gfx/geometry/mojom/geometry.mojom-lite.js", - "$root_gen_dir/ui/gfx/range/mojom/range.mojom-lite.js", - ] - - deps = [ - "//components/arc/mojom:camera_intent_js", - "//components/arc/mojom:mojom_js", - "//components/chromeos_camera/common:camera_app_helper_js", - "//media/capture/mojom:image_capture_js", - "//media/capture/video/chromeos/mojom:cros_camera_js", - "//mojo/public/js:bindings_lite", - "//third_party/blink/public/mojom:mojom_platform_js", - "//ui/gfx/geometry/mojom:mojom_js", - "//ui/gfx/range/mojom:mojom_js", - ] - - outputs = [ "$chrome_camera_app_dir/js/mojo/{{source_file_part}}" ] -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/camera_resources.grd b/chromium/chrome/browser/resources/chromeos/camera/camera_resources.grd deleted file mode 100644 index ab78c3f7507..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/camera_resources.grd +++ /dev/null @@ -1,137 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> - <outputs> - <output filename="grit/camera_resources.h" type="rc_header"> - <emit emit_type='prepend'></emit> - </output> - <output filename="grit/camera_resources_map.cc" - type="resource_file_map_source" /> - <output filename="grit/camera_resources_map.h" - type="resource_map_header" /> - <output filename="camera_resources.pak" type="data_package" /> - </outputs> - <release seq="1"> - <structures> - <structure name="IDR_CAMERA_ANALYTICS_JS" file="src/js/lib/analytics.js" type="chrome_html" /> - <structure name="IDR_CAMERA_ASYNC_WRITER_JS" file="src/js/models/async_writer.js" type="chrome_html" /> - <structure name="IDR_CAMERA_BACKGROUND_JS" file="src/js/background.js" type="chrome_html" /> - <structure name="IDR_CAMERA_BACKGROUND_OPS_JS" file="src/js/background_ops.js" type="chrome_html" /> - <structure name="IDR_CAMERA_CAMERA3_DEVICE_INFO_JS" file="src/js/device/camera3_device_info.js" type="chrome_html" /> - <structure name="IDR_CAMERA_CAMERA_INTENT_JS" file="src/js/views/camera_intent.js" type="chrome_html" /> - <structure name="IDR_CAMERA_CAMERA_JS" file="src/js/views/camera.js" type="chrome_html" /> - <structure name="IDR_CAMERA_CHROME_HELPER_JS" file="src/js/mojo/chrome_helper.js" type="chrome_html" /> - <structure name="IDR_CAMERA_CHROME_UTIL_JS" file="src/js/chrome_util.js" type="chrome_html" /> - <structure name="IDR_CAMERA_COMLINK_JS" file="src/js/lib/comlink.js" type="chrome_html" /> - <structure name="IDR_CAMERA_CONSTRAINTS_PREFERRER_JS" file="src/js/device/constraints_preferrer.js" type="chrome_html" /> - <structure name="IDR_CAMERA_DEVICE_ERROR_JS" file="src/js/device/error.js" type="chrome_html" /> - <structure name="IDR_CAMERA_DEVICE_INFO_UPDATER_JS" file="src/js/device/device_info_updater.js" type="chrome_html" /> - <structure name="IDR_CAMERA_DEVICE_OPERATOR_JS" file="src/js/mojo/device_operator.js" type="chrome_html" /> - <structure name="IDR_CAMERA_DIALOG_JS" file="src/js/views/dialog.js" type="chrome_html" /> - <structure name="IDR_CAMERA_ERROR_JS" file="src/js/error.js" type="chrome_html" /> - <structure name="IDR_CAMERA_FILENAMER_JS" file="src/js/models/filenamer.js" type="chrome_html" /> - <structure name="IDR_CAMERA_FILESYSTEM_JS" file="src/js/models/filesystem.js" type="chrome_html" /> - <structure name="IDR_CAMERA_GALLERYBUTTON_JS" file="src/js/gallerybutton.js" type="chrome_html" /> - <structure name="IDR_CAMERA_IMAGECAPTURE_JS" file="src/js/mojo/image_capture.js" type="chrome_html" /> - <structure name="IDR_CAMERA_INTENT_JS" file="src/js/intent.js" type="chrome_html" /> - <structure name="IDR_CAMERA_LAYOUT_JS" file="src/js/views/camera/layout.js" type="chrome_html" /> - <structure name="IDR_CAMERA_MAIN_CSS" file="src/css/main.css" type="chrome_html" /> - <structure name="IDR_CAMERA_MAIN_HTML" file="src/views/main.html" type="chrome_html" /> - <structure name="IDR_CAMERA_MAIN_JS" file="src/js/main.js" type="chrome_html" /> - <structure name="IDR_CAMERA_MANIFEST" file="manifest.json" type="chrome_html" /> - <structure name="IDR_CAMERA_METRICS_JS" file="src/js/metrics.js" type="chrome_html" /> - <structure name="IDR_CAMERA_MODES_JS" file="src/js/views/camera/modes.js" type="chrome_html" /> - <structure name="IDR_CAMERA_MP4_VIDEO_PROCESSOR_JS" file="src/js/models/mp4_video_processor.js" type="chrome_html" /> - <structure name="IDR_CAMERA_NAV_JS" file="src/js/nav.js" type="chrome_html" /> - <structure name="IDR_CAMERA_NOP_VIDEO_PROCESSOR_JS" file="src/js/models/nop_video_processor.js" type="chrome_html" /> - <structure name="IDR_CAMERA_OPTIONS_JS" file="src/js/views/camera/options.js" type="chrome_html" /> - <structure name="IDR_CAMERA_PERF_JS" file="src/js/perf.js" type="chrome_html" /> - <structure name="IDR_CAMERA_PREVIEW_JS" file="src/js/views/camera/preview.js" type="chrome_html" /> - <structure name="IDR_CAMERA_RECORDTIME_JS" file="src/js/views/camera/recordtime.js" type="chrome_html" /> - <structure name="IDR_CAMERA_RESULT_SAVER_JS" file="src/js/models/result_saver.js" type="chrome_html" /> - <structure name="IDR_CAMERA_REVIEW_RESULT_JS" file="src/js/views/camera/review_result.js" type="chrome_html" /> - <structure name="IDR_CAMERA_SETTINGS_JS" file="src/js/views/settings.js" type="chrome_html" /> - <structure name="IDR_CAMERA_SOUND_JS" file="src/js/sound.js" type="chrome_html" /> - <structure name="IDR_CAMERA_STATE_JS" file="src/js/state.js" type="chrome_html" /> - <structure name="IDR_CAMERA_TIMERTICK_JS" file="src/js/views/camera/timertick.js" type="chrome_html" /> - <structure name="IDR_CAMERA_TOAST_JS" file="src/js/toast.js" type="chrome_html" /> - <structure name="IDR_CAMERA_TOOLTIP_JS" file="src/js/tooltip.js" type="chrome_html" /> - <structure name="IDR_CAMERA_TYPE_JS" file="src/js/type.js" type="chrome_html" /> - <structure name="IDR_CAMERA_UTIL_JS" file="src/js/util.js" type="chrome_html" /> - <structure name="IDR_CAMERA_VIDEO_SAVER_JS" file="src/js/models/video_saver.js" type="chrome_html" /> - <structure name="IDR_CAMERA_VIEW_JS" file="src/js/views/view.js" type="chrome_html" /> - <structure name="IDR_CAMERA_WAITABLE_EVENT_JS" file="src/js/models/waitable_event.js" type="chrome_html" /> - <structure name="IDR_CAMERA_WARNING_JS" file="src/js/views/warning.js" type="chrome_html" /> - <structure name="IDR_CAMERA_WEBUI_BROWSER_PROXY" file="src/js/browser_proxy/webui_browser_proxy.js" type="chrome_html" /> - </structures> - <includes> - <!-- Mojo Lite Bindings --> - <include name="IDR_CAMERA_CAMERA_INTENT_MOJOM_LITE_JS" - file="${root_gen_dir}/components/arc/mojom/camera_intent.mojom-lite.js" - use_base_dir="false" - type="BINDATA"/> - <include name="IDR_CAMERA_IMAGE_CAPTURE_MOJOM_LITE_JS" - file="${root_gen_dir}/media/capture/mojom/image_capture.mojom-lite.js" - use_base_dir="false" - type="BINDATA"/> - <include name="IDR_CAMERA_CAMERA_COMMON_MOJOM_LITE_JS" - file="${root_gen_dir}/media/capture/video/chromeos/mojom/camera_common.mojom-lite.js" - use_base_dir="false" - type="BINDATA"/> - <include name="IDR_CAMERA_CAMERA_METADATA_MOJOM_LITE_JS" - file="${root_gen_dir}/media/capture/video/chromeos/mojom/camera_metadata.mojom-lite.js" - use_base_dir="false" - type="BINDATA"/> - <include name="IDR_CAMERA_CAMERA_METADATA_TAGS_MOJOM_LITE_JS" - file="${root_gen_dir}/media/capture/video/chromeos/mojom/camera_metadata_tags.mojom-lite.js" - use_base_dir="false" - type="BINDATA"/> - <include name="IDR_CAMERA_APP_MOJOM_LITE_JS" - file="${root_gen_dir}/media/capture/video/chromeos/mojom/camera_app.mojom-lite.js" - use_base_dir="false" - type="BINDATA"/> - - <!-- TODO(crbug.com/980846): Add FFMpeg library here with comrpession enabled once video recording is ready to test in SWA --> - - <include name="IDR_CAMERA_RECORD_END_OGG" file="src/sounds/record_end.ogg" type="BINDATA" /> - <include name="IDR_CAMERA_RECORD_START_OGG" file="src/sounds/record_start.ogg" type="BINDATA" /> - <include name="IDR_CAMERA_SHUTTER_OGG" file="src/sounds/shutter.ogg" type="BINDATA" /> - <include name="IDR_CAMERA_TICK_FINAL_OGG" file="src/sounds/tick_final.ogg" type="BINDATA" /> - <include name="IDR_CAMERA_TICK_INC_OGG" file="src/sounds/tick_inc.ogg" type="BINDATA" /> - <include name="IDR_CAMERA_TICK_START_OGG" file="src/sounds/tick_start.ogg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_MODE_SQUARE_SVG" file="src/images/camera_mode_square.svg" type="BINDATA" /> - <include name="IDR_CAMERA_SETTINGS_BUTTON_BACK_SVG" file="src/images/settings_button_back.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_MODE_PORTRAIT_SVG" file="src/images/camera_mode_portrait.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_TIMER_ON_3S_SVG" file="src/images/camera_button_timer_on_3s.svg" type="BINDATA" /> - <include name="IDR_CAMERA_SPINNER_SVG" file="src/images/spinner.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_GRID_OFF_SVG" file="src/images/camera_button_grid_off.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_MIC_ON_SVG" file="src/images/camera_button_mic_on.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_MODE_VIDEO_SVG" file="src/images/camera_mode_video.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_SHUTTER_PHOTO_STOP_SVG" file="src/images/camera_shutter_photo_stop.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_MIC_OFF_SVG" file="src/images/camera_button_mic_off.svg" type="BINDATA" /> - <include name="IDR_CAMERA_SETTINGS_RESOLUTION_SVG" file="src/images/settings_resolution.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_APP_ICONS_48_PNG" file="src/images/camera_app_icons_48.png" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_TIMER_OFF_SVG" file="src/images/camera_button_timer_off.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_SHUTTER_PHOTO_START_ACTIVE_SVG" file="src/images/camera_shutter_photo_start_active.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_APP_ICONS_128_PNG" file="src/images/camera_app_icons_128.png" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_APP_ICONS_192_PNG" file="src/images/camera_app_icons_192.png" type="BINDATA" /> - <include name="IDR_CAMERA_SETTINGS_TIMER_DURATION_SVG" file="src/images/settings_timer_duration.svg" type="BINDATA" /> - <include name="IDR_CAMERA_SETTINGS_HELP_SVG" file="src/images/settings_help.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_MIRROR_ON_SVG" file="src/images/camera_button_mirror_on.svg" type="BINDATA" /> - <include name="IDR_CAMERA_SETTINGS_BUTTON_EXPAND_SVG" file="src/images/settings_button_expand.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_GRID_ON_SVG" file="src/images/camera_button_grid_on.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_SWITCH_DEVICE_SVG" file="src/images/camera_button_switch_device.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_SHUTTER_PHOTO_STOP_HOVER_SVG" file="src/images/camera_shutter_photo_stop_hover.svg" type="BINDATA" /> - <include name="IDR_CAMERA_SETTINGS_GRID_TYPE_SVG" file="src/images/settings_grid_type.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_MIRROR_OFF_SVG" file="src/images/camera_button_mirror_off.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_SHUTTER_PHOTO_START_SVG" file="src/images/camera_shutter_photo_start.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_SWITCH_PHOTO_SVG" file="src/images/camera_button_switch_photo.svg" type="BINDATA" /> - <include name="IDR_CAMERA_SETTINGS_FEEDBACK_SVG" file="src/images/settings_feedback.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_SWITCH_VIDEO_SVG" file="src/images/camera_button_switch_video.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_SHUTTER_PHOTO_START_HOVER_SVG" file="src/images/camera_shutter_photo_start_hover.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_TIMER_ON_10S_SVG" file="src/images/camera_button_timer_on_10s.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_MODE_PHOTO_SVG" file="src/images/camera_mode_photo.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_FOCUS_AIM_SVG" file="src/images/camera_focus_aim.svg" type="BINDATA" /> - <include name="IDR_CAMERA_CAMERA_BUTTON_SETTINGS_SVG" file="src/images/camera_button_settings.svg" type="BINDATA" /> - </includes> - </release> -</grit> diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn deleted file mode 100644 index 4e76d7e52c3..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") - -group("closure_compile") { - deps = [ - ":compile_resources", - "browser_proxy:closure_compile", - "device:closure_compile", - "models:closure_compile", - "mojo:closure_compile", - "views:closure_compile", - ] -} - -js_type_check("compile_resources") { - deps = [ - ":background", - ":background_ops", - ":chrome_util", - ":error", - ":gallerybutton", - ":intent", - ":main", - ":metrics", - ":nav", - ":perf", - ":sound", - ":state", - ":toast", - ":tooltip", - ":type", - ":util", - ] -} - -js_library("chrome_util") { -} - -js_library("error") { - deps = [ ":metrics" ] -} - -js_library("intent") { - deps = [ - ":chrome_util", - ":metrics", - ":type", - "mojo:chrome_helper", - ] -} - -js_library("gallerybutton") { - deps = [ - ":chrome_util", - "models:filesystem", - "models:result_saver", - "models:video_saver", - ] - externs_list = [ - "$externs_path/file_manager_private.js", - "$externs_path/file_system_provider.js", - ] -} - -js_library("metrics") { - deps = [ - ":state", - "externs:universal_analytics_api", - ] -} - -js_library("sound") { -} - -js_library("type") { -} - -js_library("main") { - deps = [ - ":background_ops", - ":chrome_util", - ":gallerybutton", - ":intent", - ":state", - ":type", - "device:constraints_preferrer", - "device:device_info_updater", - "views:camera", - "views:camera_intent", - "views:dialog", - "views:settings", - "views:warning", - ] -} - -js_library("nav") { - deps = [ - "mojo:device_operator", - "views:view", - ] -} - -js_library("perf") { -} - -js_library("state") { - deps = [ - ":perf", - ":type", - ] -} - -js_library("background") { - deps = [ - ":background_ops", - ":intent", - ] -} - -js_library("background_ops") { - deps = [ - ":chrome_util", - ":error", - ":intent", - ":perf", - ] -} - -js_library("toast") { - deps = [ ":util" ] -} - -js_library("tooltip") { - deps = [ ":chrome_util" ] -} - -js_library("util") { - deps = [ - ":state", - ":tooltip", - ":type", - "browser_proxy:browser_proxy", - "externs:w3c_api", - "mojo:chrome_helper", - ] - externs_list = [ "$externs_path/chrome_extensions.js" ] -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn deleted file mode 100644 index 909b9b4aea2..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") - -js_type_check("closure_compile") { - deps = [ ":browser_proxy" ] -} - -js_library("browser_proxy") { - deps = [ - "..:chrome_util", - "../mojo:chrome_helper", - ] - sources = [ - "browser_proxy.js", - "browser_proxy_interface.js", - "webui_browser_proxy.js", - ] - externs_list = [ - "../externs/chrome.js", - "$externs_path/chrome_extensions.js", - "$externs_path/file_manager_private.js", - "$externs_path/file_system_provider.js", - "$externs_path/metrics_private.js", - ] -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn deleted file mode 100644 index f4b59b69732..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") - -js_type_check("closure_compile") { - deps = [ - ":camera3_device_info", - ":constraints_preferrer", - ":device_info_updater", - ":error", - ] -} - -js_library("camera3_device_info") { - deps = [ - "..:type", - "../mojo:image_capture", - ] -} - -js_library("constraints_preferrer") { - deps = [ - ":camera3_device_info", - "..:chrome_util", - "..:state", - "..:type", - "../browser_proxy:browser_proxy", - ] -} - -js_library("device_info_updater") { - deps = [ - ":camera3_device_info", - ":constraints_preferrer", - ":error", - "..:state", - "..:type", - ] -} - -js_library("error") { -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn deleted file mode 100644 index cae1c53cb2d..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") - -js_library("universal_analytics_api") { - sources = [] - - externs_list = [ "universal_analytics_api.js" ] -} - -js_library("w3c_api") { - sources = [] - - externs_list = [ "w3c_api.js" ] -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/lib/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/lib/BUILD.gn deleted file mode 100644 index 67207741560..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/js/lib/BUILD.gn +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") - -js_library("comlink") { - sources = [ "comlink.js" ] -} - -js_library("ffmpeg") { - sources = [ "ffmpeg.js" ] -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn deleted file mode 100644 index e2c787dd54f..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") - -js_type_check("closure_compile") { - deps = [ - ":filenamer", - ":filesystem", - ":result_saver", - ":video_saver", - ] -} - -js_library("filenamer") { -} - -js_library("filesystem") { - deps = [ - ":filenamer", - "../browser_proxy:browser_proxy", - ] -} - -js_library("result_saver") { -} - -js_library("video_saver") { - sources = [ - "async_writer.js", - "mp4_video_processor.js", - "nop_video_processor.js", - "video_saver.js", - "waitable_event.js", - ] - deps = [ - "..:intent", - "../externs:w3c_api", - "../lib:comlink", - "../lib:ffmpeg", - ] -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn deleted file mode 100644 index b1bdcd32ae1..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") - -js_type_check("closure_compile") { - deps = [ - ":chrome_helper", - ":device_operator", - ":image_capture", - ] -} - -js_library("chrome_helper") { - deps = [ - "//components/arc/mojom:camera_intent_js_library_for_compile", - "//components/chromeos_camera/common:camera_app_helper_js_library_for_compile", - "//third_party/blink/public/mojom:mojom_platform_js_library_for_compile", - ] - externs_list = [ "$externs_path/pending.js" ] -} - -js_library("device_operator") { - deps = [ - "..:type", - "//media/capture/video/chromeos/mojom:cros_camera_js_library_for_compile", - ] - externs_list = [ "$externs_path/pending.js" ] -} - -js_library("image_capture") { - deps = [ - ":device_operator", - "..:util", - "//media/capture/mojom:image_capture_js_library_for_compile", - ] - externs_list = [ "$externs_path/pending.js" ] -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn deleted file mode 100644 index 6cfbb72e337..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") - -group("closure_compile") { - deps = [ - ":compile_resources", - "camera:compile_resources", - ] -} - -js_type_check("compile_resources") { - deps = [ - ":camera", - ":camera_intent", - ":dialog", - ":settings", - ":view", - ":warning", - ] -} - -js_library("camera") { - deps = [ - "..:background_ops", - "..:chrome_util", - "..:metrics", - "..:type", - "../models:result_saver", - "camera:layout", - "camera:modes", - "camera:options", - "camera:preview", - "camera:timertick", - ] -} - -js_library("dialog") { -} - -js_library("camera_intent") { - deps = [ - ":camera", - "..:chrome_util", - "../models:video_saver", - "camera:review_result", - ] -} - -js_library("settings") { - deps = [ - ":view", - "..:nav", - "..:type", - "../device:camera3_device_info", - "../device:device_info_updater", - ] -} - -js_library("view") { - deps = [ "..:toast" ] -} - -js_library("warning") { -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn deleted file mode 100644 index 97fdd2dce89..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/closure_compiler/compile_js.gni") - -group("closure_compile") { - deps = [ ":compile_resources" ] -} - -js_type_check("compile_resources") { - deps = [ - ":layout", - ":modes", - ":options", - ":preview", - ":recordtime", - ":review_result", - ":timertick", - "../../mojo:device_operator", - ] -} - -js_library("layout") { - deps = [ - "../..:chrome_util", - "../..:type", - ] -} - -js_library("modes") { - deps = [ - ":recordtime", - "../..:sound", - "../..:toast", - "../..:type", - "../..:util", - "../../device:constraints_preferrer", - "../../models:filenamer", - "../../models:filesystem", - "../../models:video_saver", - "../../mojo:image_capture", - "//media/capture/video/chromeos/mojom:cros_camera_js_library_for_compile", - ] -} - -js_library("options") { - deps = [ - "../..:nav", - "../..:type", - "../..:util", - "../../device:device_info_updater", - "//components/chromeos_camera/common:camera_app_helper_js_library_for_compile", - ] -} - -js_library("preview") { - deps = [ - "../..:chrome_util", - "../..:nav", - "../..:type", - "//media/capture/video/chromeos/mojom:cros_camera_js_library_for_compile", - ] -} - -js_library("recordtime") { -} - -js_library("review_result") { - deps = [ - "../..:state", - "../..:util", - ] -} - -js_library("timertick") { -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn deleted file mode 100644 index 6535e9e8673..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//chrome/common/features.gni") -import("//tools/grit/grit_rule.gni") - -chrome_camera_app_dir = "$root_out_dir/resources/chromeos/camera" - -grit("camera_strings") { - source = "camera_strings.grd" - defines = chrome_grit_defines - outputs = [ - "_locales/am/messages.json", - "_locales/ar/messages.json", - "_locales/bg/messages.json", - "_locales/bn/messages.json", - "_locales/ca/messages.json", - "_locales/cs/messages.json", - "_locales/da/messages.json", - "_locales/de/messages.json", - "_locales/el/messages.json", - "_locales/en_GB/messages.json", - "_locales/en/messages.json", - "_locales/es/messages.json", - "_locales/es_419/messages.json", - "_locales/et/messages.json", - "_locales/fa/messages.json", - "_locales/fi/messages.json", - "_locales/fil/messages.json", - "_locales/fr/messages.json", - "_locales/gu/messages.json", - "_locales/he/messages.json", - "_locales/hi/messages.json", - "_locales/hr/messages.json", - "_locales/hu/messages.json", - "_locales/id/messages.json", - "_locales/it/messages.json", - "_locales/ja/messages.json", - "_locales/kn/messages.json", - "_locales/ko/messages.json", - "_locales/lt/messages.json", - "_locales/lv/messages.json", - "_locales/ml/messages.json", - "_locales/mr/messages.json", - "_locales/ms/messages.json", - "_locales/nl/messages.json", - "_locales/nb/messages.json", - "_locales/pl/messages.json", - "_locales/pt_BR/messages.json", - "_locales/pt_PT/messages.json", - "_locales/ro/messages.json", - "_locales/ru/messages.json", - "_locales/sk/messages.json", - "_locales/sl/messages.json", - "_locales/sr/messages.json", - "_locales/sv/messages.json", - "_locales/sw/messages.json", - "_locales/ta/messages.json", - "_locales/te/messages.json", - "_locales/th/messages.json", - "_locales/tr/messages.json", - "_locales/uk/messages.json", - "_locales/vi/messages.json", - "_locales/zh_CN/messages.json", - "_locales/zh_TW/messages.json", - ] - output_dir = chrome_camera_app_dir - - resource_ids = "" -} diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd b/chromium/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd deleted file mode 100644 index f22c312b325..00000000000 --- a/chromium/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd +++ /dev/null @@ -1,366 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<grit base_dir="." current_release="1" latest_public_release="0" - output_all_resource_defines="false" enc_check="möl" source_lang_id="en"> - <outputs> - <output filename="_locales/am/messages.json" type="chrome_messages_json" lang="am"/> - <output filename="_locales/ar/messages.json" type="chrome_messages_json" lang="ar"/> - <output filename="_locales/bg/messages.json" type="chrome_messages_json" lang="bg"/> - <output filename="_locales/bn/messages.json" type="chrome_messages_json" lang="bn"/> - <output filename="_locales/ca/messages.json" type="chrome_messages_json" lang="ca"/> - <output filename="_locales/cs/messages.json" type="chrome_messages_json" lang="cs"/> - <output filename="_locales/da/messages.json" type="chrome_messages_json" lang="da"/> - <output filename="_locales/de/messages.json" type="chrome_messages_json" lang="de"/> - <output filename="_locales/el/messages.json" type="chrome_messages_json" lang="el"/> - <output filename="_locales/en_GB/messages.json" type="chrome_messages_json" lang="en-GB"/> - <output filename="_locales/en/messages.json" type="chrome_messages_json" lang="en"/> - <output filename="_locales/es/messages.json" type="chrome_messages_json" lang="es"/> - <output filename="_locales/es_419/messages.json" type="chrome_messages_json" lang="es-419"/> - <output filename="_locales/et/messages.json" type="chrome_messages_json" lang="et"/> - <output filename="_locales/fa/messages.json" type="chrome_messages_json" lang="fa"/> - <output filename="_locales/fi/messages.json" type="chrome_messages_json" lang="fi"/> - <output filename="_locales/fil/messages.json" type="chrome_messages_json" lang="fil"/> - <output filename="_locales/fr/messages.json" type="chrome_messages_json" lang="fr"/> - <output filename="_locales/gu/messages.json" type="chrome_messages_json" lang="gu"/> - <output filename="_locales/he/messages.json" type="chrome_messages_json" lang="he"/> - <output filename="_locales/hi/messages.json" type="chrome_messages_json" lang="hi"/> - <output filename="_locales/hr/messages.json" type="chrome_messages_json" lang="hr"/> - <output filename="_locales/hu/messages.json" type="chrome_messages_json" lang="hu"/> - <output filename="_locales/id/messages.json" type="chrome_messages_json" lang="id"/> - <output filename="_locales/it/messages.json" type="chrome_messages_json" lang="it"/> - <output filename="_locales/ja/messages.json" type="chrome_messages_json" lang="ja"/> - <output filename="_locales/kn/messages.json" type="chrome_messages_json" lang="kn"/> - <output filename="_locales/ko/messages.json" type="chrome_messages_json" lang="ko"/> - <output filename="_locales/lt/messages.json" type="chrome_messages_json" lang="lt"/> - <output filename="_locales/lv/messages.json" type="chrome_messages_json" lang="lv"/> - <output filename="_locales/ml/messages.json" type="chrome_messages_json" lang="ml"/> - <output filename="_locales/mr/messages.json" type="chrome_messages_json" lang="mr"/> - <output filename="_locales/ms/messages.json" type="chrome_messages_json" lang="ms"/> - <output filename="_locales/nl/messages.json" type="chrome_messages_json" lang="nl"/> - <output filename="_locales/nb/messages.json" type="chrome_messages_json" lang="no"/> - <output filename="_locales/pl/messages.json" type="chrome_messages_json" lang="pl"/> - <output filename="_locales/pt_BR/messages.json" type="chrome_messages_json" lang="pt-BR"/> - <output filename="_locales/pt_PT/messages.json" type="chrome_messages_json" lang="pt-PT"/> - <output filename="_locales/ro/messages.json" type="chrome_messages_json" lang="ro"/> - <output filename="_locales/ru/messages.json" type="chrome_messages_json" lang="ru"/> - <output filename="_locales/sk/messages.json" type="chrome_messages_json" lang="sk"/> - <output filename="_locales/sl/messages.json" type="chrome_messages_json" lang="sl"/> - <output filename="_locales/sr/messages.json" type="chrome_messages_json" lang="sr"/> - <output filename="_locales/sv/messages.json" type="chrome_messages_json" lang="sv"/> - <output filename="_locales/sw/messages.json" type="chrome_messages_json" lang="sw"/> - <output filename="_locales/ta/messages.json" type="chrome_messages_json" lang="ta"/> - <output filename="_locales/te/messages.json" type="chrome_messages_json" lang="te"/> - <output filename="_locales/th/messages.json" type="chrome_messages_json" lang="th"/> - <output filename="_locales/tr/messages.json" type="chrome_messages_json" lang="tr"/> - <output filename="_locales/uk/messages.json" type="chrome_messages_json" lang="uk"/> - <output filename="_locales/vi/messages.json" type="chrome_messages_json" lang="vi"/> - <output filename="_locales/zh_CN/messages.json" type="chrome_messages_json" lang="zh-CN"/> - <output filename="_locales/zh_TW/messages.json" type="chrome_messages_json" lang="zh-TW"/> - </outputs> - <translations> - <file path="camera_strings_af.xtb" lang="af" /> - <file path="camera_strings_am.xtb" lang="am" /> - <file path="camera_strings_ar.xtb" lang="ar" /> - <file path="camera_strings_as.xtb" lang="as" /> - <file path="camera_strings_az.xtb" lang="az" /> - <file path="camera_strings_be.xtb" lang="be" /> - <file path="camera_strings_bg.xtb" lang="bg" /> - <file path="camera_strings_bn.xtb" lang="bn" /> - <file path="camera_strings_bs.xtb" lang="bs" /> - <file path="camera_strings_ca.xtb" lang="ca" /> - <file path="camera_strings_cs.xtb" lang="cs" /> - <file path="camera_strings_da.xtb" lang="da" /> - <file path="camera_strings_de.xtb" lang="de" /> - <file path="camera_strings_el.xtb" lang="el" /> - <file path="camera_strings_en-GB.xtb" lang="en-GB" /> - <file path="camera_strings_es.xtb" lang="es" /> - <file path="camera_strings_es-419.xtb" lang="es-419" /> - <file path="camera_strings_et.xtb" lang="et" /> - <file path="camera_strings_eu.xtb" lang="eu" /> - <file path="camera_strings_fa.xtb" lang="fa" /> - <file path="camera_strings_fi.xtb" lang="fi" /> - <file path="camera_strings_fil.xtb" lang="fil" /> - <file path="camera_strings_fr.xtb" lang="fr" /> - <file path="camera_strings_fr-CA.xtb" lang="fr-CA" /> - <file path="camera_strings_gl.xtb" lang="gl" /> - <file path="camera_strings_gu.xtb" lang="gu" /> - <file path="camera_strings_hi.xtb" lang="hi" /> - <file path="camera_strings_hr.xtb" lang="hr" /> - <file path="camera_strings_hu.xtb" lang="hu" /> - <file path="camera_strings_hy.xtb" lang="hy" /> - <file path="camera_strings_id.xtb" lang="id" /> - <file path="camera_strings_is.xtb" lang="is" /> - <file path="camera_strings_it.xtb" lang="it" /> - <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. --> - <file path="camera_strings_iw.xtb" lang="he" /> - <file path="camera_strings_ja.xtb" lang="ja" /> - <file path="camera_strings_ka.xtb" lang="ka" /> - <file path="camera_strings_kk.xtb" lang="kk" /> - <file path="camera_strings_km.xtb" lang="km" /> - <file path="camera_strings_kn.xtb" lang="kn" /> - <file path="camera_strings_ko.xtb" lang="ko" /> - <file path="camera_strings_ky.xtb" lang="ky" /> - <file path="camera_strings_lo.xtb" lang="lo" /> - <file path="camera_strings_lt.xtb" lang="lt" /> - <file path="camera_strings_lv.xtb" lang="lv" /> - <file path="camera_strings_mk.xtb" lang="mk" /> - <file path="camera_strings_ml.xtb" lang="ml" /> - <file path="camera_strings_mn.xtb" lang="mn" /> - <file path="camera_strings_mr.xtb" lang="mr" /> - <file path="camera_strings_ms.xtb" lang="ms" /> - <file path="camera_strings_my.xtb" lang="my" /> - <file path="camera_strings_ne.xtb" lang="ne" /> - <file path="camera_strings_nl.xtb" lang="nl" /> - <file path="camera_strings_no.xtb" lang="no" /> - <file path="camera_strings_or.xtb" lang="or" /> - <file path="camera_strings_pa.xtb" lang="pa" /> - <file path="camera_strings_pl.xtb" lang="pl" /> - <file path="camera_strings_pt-BR.xtb" lang="pt-BR" /> - <file path="camera_strings_pt-PT.xtb" lang="pt-PT" /> - <file path="camera_strings_ro.xtb" lang="ro" /> - <file path="camera_strings_ru.xtb" lang="ru" /> - <file path="camera_strings_si.xtb" lang="si" /> - <file path="camera_strings_sk.xtb" lang="sk" /> - <file path="camera_strings_sl.xtb" lang="sl" /> - <file path="camera_strings_sq.xtb" lang="sq" /> - <file path="camera_strings_sr.xtb" lang="sr" /> - <file path="camera_strings_sr-Latn.xtb" lang="sr-Latn" /> - <file path="camera_strings_sv.xtb" lang="sv" /> - <file path="camera_strings_sw.xtb" lang="sw" /> - <file path="camera_strings_ta.xtb" lang="ta" /> - <file path="camera_strings_te.xtb" lang="te" /> - <file path="camera_strings_th.xtb" lang="th" /> - <file path="camera_strings_tr.xtb" lang="tr" /> - <file path="camera_strings_uk.xtb" lang="uk" /> - <file path="camera_strings_ur.xtb" lang="ur" /> - <file path="camera_strings_uz.xtb" lang="uz" /> - <file path="camera_strings_vi.xtb" lang="vi" /> - <file path="camera_strings_zh-CN.xtb" lang="zh-CN" /> - <file path="camera_strings_zh-HK.xtb" lang="zh-HK" /> - <file path="camera_strings_zh-TW.xtb" lang="zh-TW" /> - <file path="camera_strings_zu.xtb" lang="zu" /> - </translations> - <release allow_pseudo="false" seq="1"> - <messages fallback_to_english="true"> - <message desc="Label for timer-duration: 10 seconds." name="IDS_LABEL_TIMER_10S"> - 10 seconds - </message> - <message desc="Label for the help button." name="IDS_HELP_BUTTON"> - Help - </message> - <message desc="Label for the dismissing button in the dialog." name="IDS_DIALOG_CANCEL_BUTTON"> - Cancel - </message> - <message desc="Label for the printing button." name="IDS_PRINT_BUTTON"> - Print - </message> - <message desc="Label for the gallery button." name="IDS_GALLERY_BUTTON"> - Go to gallery - </message> - <message desc="Error message shown when saving/adding a image or video to the file system failed." name="IDS_ERROR_MSG_SAVE_FILE_FAILED"> - Unable to save the file - </message> - <message desc="Label for the exporting button." name="IDS_EXPORT_BUTTON"> - Export to disk - </message> - <message desc="Label for the checkbox to toggle the countdown timer." name="IDS_TOGGLE_TIMER_BUTTON"> - Timer - </message> - <message desc="Message shown before moving all photos and videos stored in the Camera App to the Downloads folder." name="IDS_MIGRATE_PICTURES_MSG"> - Photos and videos taken with the camera will be moved to the Downloads folder. You can access them in Files. - - Apps with storage permissions will have access to your photos and videos. - </message> - <message desc="Label for spoken feedback to read out grid-type: 3x3." name="IDS_ARIA_GRID_3X3"> - 3 by 3 - </message> - <message desc="Label for the shutter button to start recording." name="IDS_RECORD_VIDEO_START_BUTTON"> - Start recording - </message> - <message desc="Label for the shutter button to stop recording." name="IDS_RECORD_VIDEO_STOP_BUTTON"> - Stop recording - </message> - <message desc="Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected." name="IDS_SWITCH_CAMERA_BUTTON"> - Switch to next camera - </message> - <message desc="Label for the button of timer-duration options." name="IDS_TIMER_DURATION_BUTTON"> - Timer duration - </message> - <message desc="Label for timer-duration: 3 seconds." name="IDS_LABEL_TIMER_3S"> - 3 seconds - </message> - <message desc="Status message for spoken feedback when video recording has been stopped." name="IDS_STATUS_MSG_RECORDING_STOPPED"> - Recording stopped - </message> - <message desc="Label for spoken feedback to read out grid-type: 4x4." name="IDS_ARIA_GRID_4X4"> - 4 by 4 - </message> - <message desc="Label for for grid-type: 4x4." name="IDS_LABEL_GRID_4X4"> - 4 x 4 - </message> - <message desc="Label for the button of camera-resolution options." name="IDS_CAMERA_RESOLUTION_BUTTON"> - Camera resolution - </message> - <message desc="Label for the button of photo-resolution options." name="IDS_PHOTO_RESOLUTION_BUTTON"> - Photo resolution - </message> - <message desc="Label for the button of video-resolution options." name="IDS_VIDEO_RESOLUTION_BUTTON"> - Video resolution - </message> - <message desc="Label for front camera." name="IDS_LABEL_FRONT_CAMERA"> - Front camera - </message> - <message desc="Label for back camera." name="IDS_LABEL_BACK_CAMERA"> - Back camera - </message> - <message desc="Label for external camera." name="IDS_LABEL_EXTERNAL_CAMERA"> - External camera - </message> - <message desc="Label for photo resolution options of specific resolution." name="IDS_LABEL_PHOTO_RESOLUTION"> - (<ph name="aspect_ratio_width">$1<ex>16</ex></ph>:<ph name="aspect_ratio_height">$2<ex>9</ex></ph>) <ph name="megapixel">$3<ex>0.9</ex></ph> mega pixel - </message> - <message desc="Label for detail photo resolution options of specific resolution." name="IDS_LABEL_DETAIL_PHOTO_RESOLUTION"> - (<ph name="aspect_ratio_width">$1<ex>16</ex></ph>:<ph name="aspect_ratio_height">$2<ex>9</ex></ph> - <ph name="width">$3<ex>1920</ex></ph>x<ph name="height">$4<ex>1080</ex></ph>) <ph name="megapixel">$5<ex>0.9</ex></ph> mega pixel - </message> - <message desc="Label for video resolution options of specific resolution." name="IDS_LABEL_VIDEO_RESOLUTION"> - HD <ph name="height">$1<ex>720</ex></ph>p (<ph name="width">$2<ex>1280</ex></ph>:<ph name="height">$1<ex>720</ex></ph>) - </message> - <message desc="Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in." name="IDS_DELETE_CONFIRMATION_MSG"> - Do you really want to remove <ph name="file">$1<ex>IMG_20160520_000000.jpg</ex></ph>? - </message> - <message desc="Label for spoken feedback to read out switch to take photo mode button." name="IDS_SWITCH_TAKE_PHOTO_BUTTON"> - Switch to take photo - </message> - <message desc="Label for switch to take photo mode button." name="IDS_LABEL_SWITCH_TAKE_PHOTO_BUTTON"> - Photo - </message> - <message desc="Label for the checkbox to toggle the grid shown on preview." name="IDS_TOGGLE_GRID_BUTTON"> - Grid - </message> - <message desc="Label for the shutter button to take photo." name="IDS_TAKE_PHOTO_BUTTON"> - Take photo - </message> - <message desc="Error message shown when it was impossible to connect to the camera due to unavailability." name="IDS_ERROR_MSG_NO_CAMERA"> - Your camera is currently unavailable. - Please check if the camera is properly connected. - </message> - <message desc="Error message shown when failing to start recording video." name="IDS_ERROR_MSG_RECORD_START_FAILED"> - Unable to start recording - </message> - <message desc="Label for the checkbox to toggle the microphone for recording video." name="IDS_TOGGLE_MIC_BUTTON"> - Microphone - </message> - <message desc="Label for the button of expert mode options." name="IDS_EXPERT_MODE_BUTTON"> - Expert mode - </message> - <message desc="Label for expert mode option: preview metadata." name="IDS_EXPERT_PREVIEW_METADATA"> - Preview metadata - </message> - <message desc="Label for expert mode option: save metadata." name="IDS_EXPERT_SAVE_METADATA"> - Save metadata - </message> - <message desc="Label for expert mode option: print performance logs." name="IDS_EXPERT_PRINT_PERFORMANCE_LOGS"> - Print performance logs - </message> - <message desc="Error message when the device does not support expert mode but tries to enable it." name="IDS_ERROR_MSG_EXPERT_MODE_NOT_SUPPORTED"> - Expert mode is not supported on this device - </message> - <message desc="Label for the feedback button." name="IDS_FEEDBACK_BUTTON"> - Send feedback - </message> - <message desc="Error message shown when failing to take photo." name="IDS_ERROR_MSG_TAKE_PHOTO_FAILED"> - Unable to take photo - </message> - <message desc="Error message shown when failing to take portrait photo." name="IDS_ERROR_MSG_TAKE_PORTRAIT_PHOTO_FAILED"> - Unable to take portrait photo - </message> - <message desc="Short description of the Camera App." name="IDS_DESCRIPTION"> - Take photos and record videos with your camera. - </message> - <message desc="Label for for grid-type: 3x3." name="IDS_LABEL_GRID_3X3"> - 3 x 3 - </message> - <message desc="Label for the shutter button to cancel countdown timer and stop taking photo." name="IDS_TAKE_PHOTO_CANCEL_BUTTON"> - Stop taking photo - </message> - <message desc="Label for the delete button." name="IDS_DELETE_BUTTON"> - Delete - </message> - <message desc="Error message shown when no data is recorded for a recording and it won't be added to the gallery." name="IDS_ERROR_MSG_EMPTY_RECORDING"> - Nothing recorded - </message> - <message desc="Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in." name="IDS_DELETE_MULTI_CONFIRMATION_MSG"> - Do you really want to remove <ph name="count">$1<ex>20</ex></ph> items? - </message> - <message desc="Text to speech label for the gallery list." name="IDS_GALLERY_IMAGES"> - Gallery images - </message> - <message desc="Error message shown when exporting to an external directory failed. Expects a file name to be passed in." name="IDS_ERROR_MSG_GALLERY_EXPORT_FAILED"> - Unable to export <ph name="file">$1<ex>IMG_20160520_000000.jpg</ex></ph> - </message> - <message desc="Status message for spoken feedback when switching over to another camera." name="IDS_STATUS_MSG_CAMERA_SWITCHED"> - <ph name="camera">$1<ex>USB WebCam (12ab:5678) User-facing</ex></ph> active - </message> - <message desc="Name of the Camera App." name="IDS_NAME"> - Camera - </message> - <message desc="Error message shown when failing to read or write the file system." name="IDS_ERROR_MSG_FILE_SYSTEM_FAILED"> - File system errors. - </message> - <message desc="Label for the settings button." name="IDS_SETTINGS_BUTTON"> - Settings - </message> - <message desc="Label for the accepting button in the dialog." name="IDS_DIALOG_OK_BUTTON"> - OK - </message> - <message desc="Label for grid-type: golden ratio." name="IDS_LABEL_GRID_GOLDEN"> - Golden ratio - </message> - <message desc="Label for spoken feedback to read out switch to record video mode button." name="IDS_SWITCH_RECORD_VIDEO_BUTTON"> - Switch to record video - </message> - <message desc="Label for switch to record video mode button." name="IDS_LABEL_SWITCH_RECORD_VIDEO_BUTTON"> - Video - </message> - <message desc="Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally." name="IDS_TOGGLE_MIRROR_BUTTON"> - Mirroring - </message> - <message desc="Label for the button of grid-type options." name="IDS_GRID_TYPE_BUTTON"> - Grid type - </message> - <message desc="Label showing current state of 30 FPS on tooltip of toggle 60 FPS recording checkbox." name="IDS_LABEL_30FPS"> - 30 FPS - </message> - <message desc="Label showing current state of 60 FPS on tooltip of toggle 60 FPS recording checkbox." name="IDS_LABEL_60FPS"> - 60 FPS - </message> - <message desc="Label for the checkbox to toggle 60 FPS recording." name="IDS_TOGGLE_60FPS_BUTTON"> - 60 FPS - </message> - <message desc="Label for the back button." name="IDS_BACK_BUTTON"> - Go back - </message> - <message desc="Label for spoken feedback to read out switch to take square photo mode button." name="IDS_SWITCH_TAKE_SQUARE_PHOTO_BUTTON"> - Switch to take square photo - </message> - <message desc="Label for switch to take square photo mode button." name="IDS_LABEL_SWITCH_TAKE_SQUARE_PHOTO_BUTTON"> - Square - </message> - <message desc="Label for spoken feedback to read out switch to take portrait photo mode button." name="IDS_SWITCH_TAKE_PORTRAIT_PHOTO_BUTTON"> - Switch to take portrait photo - </message> - <message desc="Label for switch to take portrait photo mode button." name="IDS_LABEL_SWITCH_TAKE_PORTRAIT_PHOTO_BUTTON"> - Portrait - </message> - <message desc="Label for the confirm button to confirm with the reviewed photo or video." name="IDS_CONFIRM_REVIEW_BUTTON"> - Confirm - </message> - <message desc="Label for the cancel button to cancel with the reviewed photo or video." name="IDS_CANCEL_REVIEW_BUTTON"> - Cancel - </message> - <message desc="Label for the button to play video." name="IDS_PLAY_RESULT_VIDEO_BUTTON"> - Play video - </message> - </messages> - </release> -</grit> diff --git a/chromium/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn b/chromium/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn index f899962417a..af80c45ce88 100644 --- a/chromium/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn @@ -29,9 +29,9 @@ js_library("internet_config_dialog") { "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", ] - externs_list = [ - "$externs_path/chrome_send.js", - "$externs_path/networking_private.js", - ] + externs_list = chrome_extension_public_externs + [ + "$externs_path/chrome_send.js", + "$externs_path/networking_private.js", + ] extra_sources = [ "$interfaces_path/networking_private_interface.js" ] } diff --git a/chromium/chrome/browser/resources/chromeos/login/BUILD.gn b/chromium/chrome/browser/resources/chromeos/login/BUILD.gn index c453524aa61..6e02f0073a2 100644 --- a/chromium/chrome/browser/resources/chromeos/login/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/login/BUILD.gn @@ -17,7 +17,6 @@ js_type_check("closure_compile") { ":gaia_buttons", ":gaia_card", ":gaia_header", - ":gaia_input", ":gaia_input_form", ":gaia_password_changed", ":gesture_navigation", @@ -141,11 +140,13 @@ js_library("gaia_header") { js_library("gaia_input_form") { } -js_library("gaia_input") { -} - js_library("gaia_password_changed") { - deps = [ "components:oobe_i18n_behavior" ] + deps = [ + "components:login_screen_behavior", + "components:multi_step_behavior", + "components:oobe_dialog_host_behavior", + "components:oobe_i18n_behavior", + ] } js_library("gesture_navigation") { @@ -186,6 +187,15 @@ js_library("offline_gaia") { js_library("oobe_a11y_option") { } +js_library("oobe_adb_sideloading_screen") { + deps = [ + "components:login_screen_behavior", + "components:multi_step_behavior", + "components:oobe_dialog_host_behavior", + "components:oobe_i18n_behavior", + ] +} + js_library("oobe_enable_kiosk") { deps = [ "components:login_screen_behavior", @@ -229,6 +239,7 @@ js_library("oobe_supervision_transition") { js_library("oobe_update") { deps = [ + "components:login_screen_behavior", "components:oobe_dialog_host_behavior", "components:oobe_i18n_behavior", ] @@ -236,13 +247,19 @@ js_library("oobe_update") { js_library("recommend_apps") { deps = [ + "components:login_screen_behavior", + "components:multi_step_behavior", "components:oobe_dialog_host_behavior", "components:oobe_i18n_behavior", + "components:oobe_types", ] } js_library("saml_confirm_password") { - deps = [ "components:oobe_i18n_behavior" ] + deps = [ + "components:oobe_dialog_host_behavior", + "components:oobe_i18n_behavior", + ] } js_library("sync_consent") { diff --git a/chromium/chrome/browser/resources/chromeos/login/components/BUILD.gn b/chromium/chrome/browser/resources/chromeos/login/components/BUILD.gn index 59876172124..a104ef10d39 100644 --- a/chromium/chrome/browser/resources/chromeos/login/components/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/login/components/BUILD.gn @@ -11,6 +11,7 @@ js_type_check("closure_compile") { ":hd-iron-icon", ":html-echo", ":login_screen_behavior", + ":multi_step_behavior", ":oobe_buttons", ":oobe_dialog", ":oobe_dialog_host_behavior", @@ -49,6 +50,9 @@ js_library("login_screen_behavior") { ] } +js_library("multi_step_behavior") { +} + js_library("oobe_buttons") { deps = [ ":oobe_i18n_behavior" ] } @@ -56,9 +60,9 @@ js_library("oobe_buttons") { js_library("oobe_dialog") { deps = [ ":fake_oobe", - "//ui/webui/resources/cr_elements:cr_scrollable_behavior", "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render", ] + externs_list = [ "$externs_path/pending.js" ] } js_library("oobe_dialog_host_behavior") { diff --git a/chromium/chrome/browser/resources/chromeos/network_ui/BUILD.gn b/chromium/chrome/browser/resources/chromeos/network_ui/BUILD.gn index 6060563b75e..85383abad38 100644 --- a/chromium/chrome/browser/resources/chromeos/network_ui/BUILD.gn +++ b/chromium/chrome/browser/resources/chromeos/network_ui/BUILD.gn @@ -5,18 +5,43 @@ import("//third_party/closure_compiler/compile_js.gni") js_type_check("closure_compile") { - deps = [ ":network_ui" ] + deps = [ + ":network_logs_ui", + ":network_state_ui", + ":network_ui", + ":network_ui_browser_proxy", + ] } js_library("network_ui") { deps = [ + ":network_ui_browser_proxy", + "//ui/webui/resources/cr_components/chromeos/network:onc_mojo", + "//ui/webui/resources/js:i18n_behavior", + "//ui/webui/resources/js:load_time_data", + ] +} + +js_library("network_logs_ui") { + deps = [ + ":network_ui_browser_proxy", + "//ui/webui/resources/js:i18n_behavior", + ] +} + +js_library("network_state_ui") { + deps = [ + ":network_ui_browser_proxy", "//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile", "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider", "//ui/webui/resources/cr_components/chromeos/network:network_icon", "//ui/webui/resources/cr_components/chromeos/network:network_list", "//ui/webui/resources/cr_components/chromeos/network:onc_mojo", - "//ui/webui/resources/js:load_time_data", - "//ui/webui/resources/js:util", ] - externs_list = [ "$externs_path/networking_private.js" ] + externs_list = chrome_extension_public_externs + + [ "$externs_path/networking_private.js" ] +} + +js_library("network_ui_browser_proxy") { + deps = [ "//ui/webui/resources/js:cr" ] } diff --git a/chromium/chrome/browser/resources/component_extension_resources.grd b/chromium/chrome/browser/resources/component_extension_resources.grd index cf1d5e9e58b..7989a4c8ebe 100644 --- a/chromium/chrome/browser/resources/component_extension_resources.grd +++ b/chromium/chrome/browser/resources/component_extension_resources.grd @@ -101,8 +101,10 @@ <include name="IDR_PDF_INDEX_HTML" file="pdf/index.html" type="BINDATA" preprocess="true" /> <include name="IDR_PDF_INDEX_CSS" file="pdf/index.css" type="BINDATA" /> <include name="IDR_PDF_MAIN_JS" file="pdf/main.js" type="BINDATA" preprocess="true" /> - <include name="IDR_PDF_MAIN_UTIL_JS" file="pdf/main_util.js" type="BINDATA" /> - <include name="IDR_PDF_PDF_VIEWER_JS" file="pdf/pdf_viewer.js" type="BINDATA" /> + <include name="IDR_PDF_PDF_VIEWER_UTILS_JS" file="pdf/pdf_viewer_utils.js" type="BINDATA" /> + <include name="IDR_PDF_PDF_VIEWER_BASE_JS" file="pdf/pdf_viewer_base.js" type="BINDATA" /> + <include name="IDR_PDF_PDF_VIEWER_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/pdf_viewer.js" use_base_dir="false" type="BINDATA" preprocess="true" /> + <include name="IDR_PDF_PDF_VIEWER_SHARED_STYLE_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/pdf_viewer_shared_style.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_BOOKMARK_TYPE_JS" file="pdf/bookmark_type.js" type="BINDATA" /> <include name="IDR_PDF_CONSTANTS_JS" file="pdf/constants.js" type="BINDATA" /> <include name="IDR_PDF_CONTROLLER_JS" file="pdf/controller.js" type="BINDATA" /> @@ -122,6 +124,7 @@ <include name="IDR_PDF_VIEWER_BOOKMARK_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-bookmark.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_VIEWER_ERROR_SCREEN_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-error-screen.js" use_base_dir="false" type="BINDATA" /> <if expr="chromeos"> + <include name="IDR_PDF_VIEWER_INK_CONTROLLER_JS" file="pdf/ink_controller.js" type="BINDATA" /> <include name="IDR_PDF_VIEWER_INK_INDEX_HTML" file="pdf/ink/index.html" type="BINDATA" /> <include name="IDR_PDF_VIEWER_INK_INK_API_JS" file="pdf/ink/ink_api.js" type="BINDATA" /> <include name="IDR_PDF_VIEWER_INK_HOST_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-ink-host.js" use_base_dir="false" type="BINDATA" /> @@ -131,6 +134,7 @@ <include name="IDR_PDF_VIEWER_PAGE_SELECTOR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-page-selector.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_VIEWER_PASSWORD_SCREEN_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-password-screen.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js" use_base_dir="false" type="BINDATA" preprocess="true"/> + <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_NEW_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js" use_base_dir="false" type="BINDATA" preprocess="true"/> <include name="IDR_PDF_VIEWER_TOOLBAR_DROPDOWN_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_VIEWER_ZOOM_BUTTON_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-zoom-button.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_VIEWER_ZOOM_SELECTOR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js" use_base_dir="false" type="BINDATA" /> diff --git a/chromium/chrome/browser/resources/components/components.js b/chromium/chrome/browser/resources/components/components.js index f50d4b36097..e761310541f 100644 --- a/chromium/chrome/browser/resources/components/components.js +++ b/chromium/chrome/browser/resources/components/components.js @@ -26,7 +26,7 @@ function renderTemplate(componentsData) { // This is the javascript code that processes the template: const input = new JsEvalContext(componentsData); const output = $('component-template').cloneNode(true); - $('component-placeholder').innerHTML = ''; + $('component-placeholder').innerHTML = trustedTypes.emptyHTML; $('component-placeholder').appendChild(output); jstProcess(input, output); output.removeAttribute('hidden'); diff --git a/chromium/chrome/browser/resources/conflicts/about_conflicts.html b/chromium/chrome/browser/resources/conflicts/about_conflicts.html index 83c277a0bbe..855f25c63ff 100644 --- a/chromium/chrome/browser/resources/conflicts/about_conflicts.html +++ b/chromium/chrome/browser/resources/conflicts/about_conflicts.html @@ -208,7 +208,7 @@ html[dir=rtl] .clearing { jsselect="moduleList" class="module"> <td valign="top" class="datacell"> <span dir="ltr" - jsvalues=".innerHTML:description" + jsvalues=".textContent:description" class="clearing nowrap"></span> </td> <td valign="top" class="datacell"> diff --git a/chromium/chrome/browser/resources/cryptotoken/enroller.js b/chromium/chrome/browser/resources/cryptotoken/enroller.js index 4088338c9e8..12440488154 100644 --- a/chromium/chrome/browser/resources/cryptotoken/enroller.js +++ b/chromium/chrome/browser/resources/cryptotoken/enroller.js @@ -869,14 +869,10 @@ Enroller.prototype.doRegisterWebAuthn_ = function(appId, challenge, request) { return; } - const attestationPreference = - conveyancePreference(challenge) == ConveyancePreference.DIRECT ? - WebAuthnAttestationConveyancePreference.DIRECT : - WebAuthnAttestationConveyancePreference.NONE; - if (!chrome.cryptotokenPrivate) { this.doRegisterWebAuthnContinue_( - appId, encodedChallenge, request, attestationPreference); + appId, encodedChallenge, request, + WebAuthnAttestationConveyancePreference.DIRECT); return; } @@ -887,7 +883,7 @@ Enroller.prototype.doRegisterWebAuthn_ = function(appId, challenge, request) { appId, encodedChallenge, request, enterprise_context ? WebAuthnAttestationConveyancePreference.ENTERPRISE : - attestationPreference); + WebAuthnAttestationConveyancePreference.DIRECT); }); }; diff --git a/chromium/chrome/browser/resources/default_apps/external_extensions.json b/chromium/chrome/browser/resources/default_apps/external_extensions.json index 59a0f9ad07f..9449bc103f2 100644 --- a/chromium/chrome/browser/resources/default_apps/external_extensions.json +++ b/chromium/chrome/browser/resources/default_apps/external_extensions.json @@ -7,8 +7,7 @@ { "blpcfgokakmgnkcojhhkbfbldkacnbeo" : { "external_crx": "youtube.crx", - "external_version": "4.2.5", - "is_bookmark_app": true + "external_version": "4.2.5" }, "pjkljhegncpnkpknbcohdijeoejaedia" : { "external_crx": "gmail.crx", diff --git a/chromium/chrome/browser/resources/discards/OWNERS b/chromium/chrome/browser/resources/discards/OWNERS index dcd54320481..6ef4e6df1e5 100644 --- a/chromium/chrome/browser/resources/discards/OWNERS +++ b/chromium/chrome/browser/resources/discards/OWNERS @@ -1 +1 @@ -file://services/resource_coordinator/OWNERS +file://components/performance_manager/OWNERS diff --git a/chromium/chrome/browser/resources/discards/discards_tab.html b/chromium/chrome/browser/resources/discards/discards_tab.html index b91684d1b52..c4d1e25566a 100644 --- a/chromium/chrome/browser/resources/discards/discards_tab.html +++ b/chromium/chrome/browser/resources/discards/discards_tab.html @@ -206,11 +206,6 @@ </div> </div> </th> - <th data-sort-key="canFreeze" on-click="onSortClick"> - <div class="header-cell-container"> - Can freeze? - </div> - </th> <th data-sort-key="discardCount" on-click="onSortClick"> <div class="header-cell-container"> <div> @@ -258,19 +253,6 @@ <td>[[visibilityToString_(item.visibility)]]</td> <td>[[loadingStateToString_(item.loadingState)]]</td> <td>[[getLifeCycleState_(item)]]</td> - <td class="boolean-cell"> - <div>[[boolToString_(item.canFreeze)]]</div> - <div is="action-link" class="tooltip-container" - disabled$="[[!hasCannotFreezeReasons_(item)]]"> - [View Reason] - <div class="tooltip"> - <template is="dom-repeat" - items="[[item.cannotFreezeReasons]]"> - <div>[[item]]</div> - </template> - </div> - </div> - </td> <td>[[item.discardCount]]</td> <td class="boolean-cell"> <div>[[boolToString_(item.isAutoDiscardable)]]</div> @@ -286,8 +268,6 @@ <div is="action-link" on-click="loadTab_" disabled$="[[!canLoad_(item)]]"> [Load]</div> - <div is="action-link" on-click="freezeTab_" - disabled$="[[!canFreeze_(item)]]">[Freeze]</div> <div is="action-link" on-click="urgentDiscardTab_" disabled$="[[!canDiscard_(item)]]"> [Urgent Discard] diff --git a/chromium/chrome/browser/resources/discards/discards_tab.js b/chromium/chrome/browser/resources/discards/discards_tab.js index 2fef49056b5..963023218e5 100644 --- a/chromium/chrome/browser/resources/discards/discards_tab.js +++ b/chromium/chrome/browser/resources/discards/discards_tab.js @@ -37,7 +37,7 @@ export function compareTabDiscardsInfos(sortKey, a, b) { } // Compares boolean fields. - if (['canFreeze', 'isAutoDiscardable'].includes(sortKey)) { + if (['isAutoDiscardable'].includes(sortKey)) { if (val1 === val2) { return 0; } @@ -219,10 +219,6 @@ Polymer({ return pageLifecycleStateFromVisibilityAndFocus(); case mojom.LifecycleUnitState.THROTTLED: return pageLifecycleStateFromVisibilityAndFocus() + ' (throttled)'; - case mojom.LifecycleUnitState.PENDING_FREEZE: - return pageLifecycleStateFromVisibilityAndFocus() + ' (pending frozen)'; - case mojom.LifecycleUnitState.FROZEN: - return 'frozen'; case mojom.LifecycleUnitState.DISCARDED: return 'discarded (' + this.discardReasonToString_(reason) + ')' + ((reason === mojom.LifecycleUnitDiscardReason.URGENT) ? ' at ' + @@ -231,8 +227,6 @@ Polymer({ (new Date(stateChangeTime.microseconds / 1000)) .toLocaleString() : ''); - case mojom.LifecycleUnitState.PENDING_UNFREEZE: - return 'frozen (pending unfreeze)'; } assertNotReached('Unknown lifecycle state: ' + state); }, @@ -331,16 +325,6 @@ Polymer({ }, /** - * Tests whether an item has reasons why it cannot be frozen. - * @param {discards.mojom.TabDiscardsInfo} item The item in question. - * @return {boolean} true iff there are reasons why the item cannot be - * frozen. - * @private - */ - hasCannotFreezeReasons_(item) { - return item.cannotFreezeReasons.length !== 0; - }, - /** * Tests whether an item has reasons why it cannot be discarded. * @param {discards.mojom.TabDiscardsInfo} item The item in question. * @return {boolean} true iff there are reasons why the item cannot be @@ -362,27 +346,6 @@ Polymer({ }, /** - * Tests whether an item can be frozen. - * @param {discards.mojom.TabDiscardsInfo} item The item in question. - * @return {boolean} true iff the item can be frozen. - * @private - */ - canFreeze_(item) { - if (item.visibility === discards.mojom.LifecycleUnitVisibility.HIDDEN || - item.visibility === discards.mojom.LifecycleUnitVisibility.OCCLUDED) { - // Only tabs that aren't visible can be frozen for now. - switch (item.state) { - case mojom.LifecycleUnitState.DISCARDED: - case mojom.LifecycleUnitState.FROZEN: - case mojom.LifecycleUnitState.PENDING_FREEZE: - return false; - } - return true; - } - return false; - }, - - /** * Tests whether an item can be discarded. * @param {discards.mojom.TabDiscardsInfo} item The item in question. * @return {boolean} true iff the item can be discarded. @@ -423,15 +386,6 @@ Polymer({ }, /** - * Event handler that freezes a tab. - * @param {Event} e The event. - * @private - */ - freezeTab_(e) { - this.discardsDetailsProvider_.freezeById(e.model.item.id); - }, - - /** * Event handler that discards a given tab urgently. * @param {Event} e The event. * @private diff --git a/chromium/chrome/browser/resources/discards/graph_doc.js b/chromium/chrome/browser/resources/discards/graph_doc.js index 37b9bc7d46d..e3ce7e1d7f8 100644 --- a/chromium/chrome/browser/resources/discards/graph_doc.js +++ b/chromium/chrome/browser/resources/discards/graph_doc.js @@ -2,25 +2,42 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Radius of a node circle. +const /** number */ kNodeRadius = 6; + // Target y position for page nodes. -const kPageNodesTargetY = 20; +const /** number */ kPageNodesTargetY = 20; // Range occupied by page nodes at the top of the graph view. -const kPageNodesYRange = 100; +const /** number */ kPageNodesYRange = 100; // Range occupied by process nodes at the bottom of the graph view. -const kProcessNodesYRange = 100; +const /** number */ kProcessNodesYRange = 100; // Range occupied by worker nodes at the bottom of the graph view, above // process nodes. -const kWorkerNodesYRange = 200; +const /** number */ kWorkerNodesYRange = 200; // Target y position for frame nodes. -const kFrameNodesTargetY = kPageNodesYRange + 50; +const /** number */ kFrameNodesTargetY = kPageNodesYRange + 50; // Range that frame nodes cannot enter at the top/bottom of the graph view. -const kFrameNodesTopMargin = kPageNodesYRange; -const kFrameNodesBottomMargin = kWorkerNodesYRange + 50; +const /** number */ kFrameNodesTopMargin = kPageNodesYRange; +const /** number */ kFrameNodesBottomMargin = kWorkerNodesYRange + 50; + +// The maximum strength of a boundary force. +// According to https://github.com/d3/d3-force#positioning, strength values +// outside the range [0,1] are "not recommended". +const /** number */ kMaxBoundaryStrength = 1; + +// The strength of a high Y-force. This is appropriate for forces that +// strongly pull towards an attractor, but can still be overridden by the +// strongest force. +const /** number */ kHighYStrength = 0.9; + +// The strength of a weak Y-force. This is appropriate for forces that exert +// some influence but can be easily overridden. +const /** number */ kWeakYStrength = 0.1; class ToolTip { /** @@ -271,10 +288,18 @@ class GraphNode { /** * @return {number} The strength of the force that pulls the node towards - * its target y position. + * its target y position. + */ + get targetYPositionStrength() { + return kWeakYStrength; + } + + /** + * @return {number} A scaling factor applied to the strength of links to this + * node. */ - targetYPositionStrength() { - return 0.1; + get linkStrengthScalingFactor() { + return 1; } /** @@ -287,12 +312,23 @@ class GraphNode { } /** @return {number} The strength of the repulsion force with other nodes. */ - manyBodyStrength() { + get manyBodyStrength() { return -200; } - /** @return {!Array<number>} */ - linkTargets() { + /** @return {!Array<number>} an array of node ids. */ + get linkTargets() { + return []; + } + + /** + * Dashed links express ownership relationships. An object can own multiple + * things, but be owned by exactly one (per relationship type). As such, the + * relationship is expressed on the *owned* object. These links are drawn with + * an arrow at the beginning of the link, pointing to the owned object. + * @return {!Array<number>} an array of node ids. + */ + get dashedLinkTargets() { return []; } @@ -322,8 +358,18 @@ class PageNode extends GraphNode { } /** @override */ - targetYPositionStrength() { - return 10; + get targetYPositionStrength() { + // Gravitate strongly towards the top of the graph. Can be overridden by + // the bounding force which uses kMaxBoundaryStrength. + return kHighYStrength; + } + + /** @override */ + get linkStrengthScalingFactor() { + // Give links from frame nodes to page nodes less weight than links between + // frame nodes, so the that Y forces pulling page nodes into their area can + // dominate over link forces pulling them towards frame nodes. + return 0.5; } /** override */ @@ -332,9 +378,17 @@ class PageNode extends GraphNode { } /** override */ - manyBodyStrength() { + get manyBodyStrength() { return -600; } + + /** override */ + get dashedLinkTargets() { + if (this.page.openerFrameId) { + return [this.page.openerFrameId]; + } + return []; + } } class FrameNode extends GraphNode { @@ -362,7 +416,7 @@ class FrameNode extends GraphNode { } /** override */ - linkTargets() { + get linkTargets() { // Only link to the page if there isn't a parent frame. return [ this.frame.parentFrameId || this.frame.pageId, this.frame.processId @@ -386,8 +440,18 @@ class ProcessNode extends GraphNode { } /** @return {number} */ - targetYPositionStrength() { - return 10; + get targetYPositionStrength() { + // Gravitate strongly towards the bottom of the graph. Can be overridden by + // the bounding force which uses kMaxBoundaryStrength. + return kHighYStrength; + } + + /** @override */ + get linkStrengthScalingFactor() { + // Give links to process nodes less weight than links between frame nodes, + // so the that Y forces pulling process nodes into their area can dominate + // over link forces pulling them towards frame nodes. + return 0.5; } /** override */ @@ -396,7 +460,7 @@ class ProcessNode extends GraphNode { } /** override */ - manyBodyStrength() { + get manyBodyStrength() { return -600; } } @@ -417,8 +481,10 @@ class WorkerNode extends GraphNode { } /** @return {number} */ - targetYPositionStrength() { - return 10; + get targetYPositionStrength() { + // Gravitate strongly towards the worker area of the graph. Can be + // overridden by the bounding force which uses kMaxBoundaryStrength. + return kHighYStrength; } /** override */ @@ -429,12 +495,12 @@ class WorkerNode extends GraphNode { } /** override */ - manyBodyStrength() { + get manyBodyStrength() { return -600; } /** override */ - linkTargets() { + get linkTargets() { // Link the process, in addition to all the client and child workers. return [ this.worker.processId, ...this.worker.clientFrameIds, @@ -444,14 +510,19 @@ class WorkerNode extends GraphNode { } /** - * A force that bounds GraphNodes |allowedYRange| in Y. + * A force that bounds GraphNodes |allowedYRange| in Y, + * as well as bounding them to stay in page bounds in X. * @param {number} graphHeight + * @param {number} graphWidth */ -function boundingForce(graphHeight) { +function boundingForce(graphHeight, graphWidth) { /** @type {!Array<!GraphNode>} */ let nodes = []; /** @type {!Array<!Array>} */ let bounds = []; + const xBounds = [2 * kNodeRadius, graphWidth - 2 * kNodeRadius]; + const boundPosition = (pos, bound) => + Math.max(bound[0], Math.min(pos, bound[1])); /** @param {number} alpha */ function force(alpha) { @@ -459,12 +530,23 @@ function boundingForce(graphHeight) { for (let i = 0; i < n; ++i) { const bound = bounds[i]; const node = nodes[i]; - const yOld = node.y; - const yNew = Math.max(bound[0], Math.min(yOld, bound[1])); - if (yOld !== yNew) { - node.y = yNew; - // Zero the velocity of clamped nodes. - node.vy = 0; + + // Calculate where the node will end up after movement. If it will be out + // of bounds apply a counter-force to bring it back in. + const yNextPosition = node.y + node.vy; + const yBoundedPosition = boundPosition(yNextPosition, bound); + if (yNextPosition !== yBoundedPosition) { + // Do not include alpha because we want to be strongly repelled from + // the boundary even if alpha has decayed. + node.vy += (yBoundedPosition - yNextPosition) * kMaxBoundaryStrength; + } + + const xNextPosition = node.x + node.vx; + const xBoundedPosition = boundPosition(xNextPosition, xBounds); + if (xNextPosition !== xBoundedPosition) { + // Do not include alpha because we want to be strongly repelled from + // the boundary even if alpha has decayed. + node.vx += (xBoundedPosition - xNextPosition) * kMaxBoundaryStrength; } } } @@ -472,7 +554,13 @@ function boundingForce(graphHeight) { /** @param {!Array<!GraphNode>} n */ force.initialize = function(n) { nodes = n; - bounds = nodes.map(node => node.allowedYRange(graphHeight)); + bounds = nodes.map(node => { + const nodeBounds = node.allowedYRange(graphHeight); + // Leave space for the node circle plus a small border. + nodeBounds[0] += kNodeRadius * 2; + nodeBounds[1] -= kNodeRadius * 2; + return nodeBounds; + }); }; return force; @@ -533,6 +621,12 @@ class Graph { */ this.linkGroup_ = null; + /** + * A selection for the top-level <g> node that contains all dashed edges. + * @private {d3.selection} + */ + this.dashedLinkGroup_ = null; + /** @private {!Map<number, !GraphNode>} */ this.nodes_ = new Map(); @@ -543,6 +637,12 @@ class Graph { this.links_ = []; /** + * The dashed links. + * @private {!Array<!d3.ForceLink>} + */ + this.dashedLinks_ = []; + + /** * The host window. * @private {Window} */ @@ -575,7 +675,17 @@ class Graph { simulation.on('tick', this.onTick_.bind(this)); const linkForce = d3.forceLink().id(d => d.id); - simulation.force('link', linkForce); + const defaultStrength = linkForce.strength(); + + // Override the default link strength function to apply scaling factors + // from the source and target nodes to the link strength. This lets + // different node types balance link forces with other forces that act on + // them. + simulation.force( + 'link', + linkForce.strength( + l => defaultStrength(l) * l.source.linkStrengthScalingFactor * + l.target.linkStrengthScalingFactor)); // Sets the repulsion force between nodes (positive number is attraction, // negative number is repulsion). @@ -588,8 +698,9 @@ class Graph { // Create the <g> elements that host nodes and links. // The link groups are created first so that all links end up behind nodes. const svg = d3.select(this.svg_); - this.toolTipLinkGroup_ = svg.append('g').attr('class', 'toolTipLinks'); + this.toolTipLinkGroup_ = svg.append('g').attr('class', 'tool-tip-links'); this.linkGroup_ = svg.append('g').attr('class', 'links'); + this.dashedLinkGroup_ = svg.append('g').attr('class', 'dashed-links'); this.nodeGroup_ = svg.append('g').attr('class', 'nodes'); this.separatorGroup_ = svg.append('g').attr('class', 'separators'); @@ -630,7 +741,11 @@ class Graph { /** @override */ pageChanged(page) { const pageNode = /** @type {!PageNode} */ (this.nodes_.get(page.id)); + + // Page node dashed links may change dynamically, so account for that here. + this.removeDashedNodeLinks_(pageNode); pageNode.page = page; + this.addDashedNodeLinks_(pageNode); } /** @override */ @@ -665,6 +780,7 @@ class Graph { // Remove any links, and then the node itself. this.removeNodeLinks_(node); + this.removeDashedNodeLinks_(node); this.nodes_.delete(nodeId); } @@ -709,12 +825,22 @@ class Graph { * @private */ removeNodeLinks_(node) { - // Filter away any links to or from the deleted node. + // Filter away any links to or from the provided node. this.links_ = this.links_.filter( link => link.source !== node && link.target !== node); } /** + * @param {!GraphNode} node + * @private + */ + removeDashedNodeLinks_(node) { + // Filter away any dashed links to or from the provided node. + this.dashedLinks_ = this.dashedLinks_.filter( + link => link.source !== node && link.target !== node); + } + + /** * @param {!Object<string>} nodeDescriptions * @private */ @@ -848,10 +974,18 @@ class Graph { // Select the links. const link = this.linkGroup_.selectAll('line').data(this.links_); // Add new links. - link.enter().append('line').attr('stroke-width', 1); + link.enter().append('line'); // Remove dead links. link.exit().remove(); + // Select the dashed links. + const dashedLink = + this.dashedLinkGroup_.selectAll('line').data(this.dashedLinks_); + // Add new dashed links. + dashedLink.enter().append('line'); + // Remove dead dashed links. + dashedLink.exit().remove(); + // Select the nodes, except for any dead ones that are still transitioning. const nodes = Array.from(this.nodes_.values()); const node = @@ -863,8 +997,10 @@ class Graph { .append('g') .call(this.drag_) .on('click', this.onGraphNodeClick_.bind(this)); - const circles = newNodes.append('circle').attr('r', 9).attr( - 'fill', 'green'); // New nodes appear green. + const circles = newNodes.append('circle') + .attr('id', d => `circle-${d.id}`) + .attr('r', kNodeRadius * 1.5) + .attr('fill', 'green'); // New nodes appear green. newNodes.append('image') .attr('x', -8) @@ -877,7 +1013,7 @@ class Graph { circles.transition() .duration(2000) .attr('fill', d => d.color) - .attr('r', 6); + .attr('r', kNodeRadius); } if (!node.exit().empty()) { @@ -913,9 +1049,11 @@ class Graph { // Update and restart the simulation if the graph changed. if (!node.enter().empty() || !node.exit().empty() || - !link.enter().empty() || !link.exit().empty()) { + !link.enter().empty() || !link.exit().empty() || + !dashedLink.enter().empty() || !dashedLink.exit().empty()) { this.simulation_.nodes(nodes); - this.simulation_.force('link').links(this.links_); + const links = this.links_.concat(this.dashedLinks_); + this.simulation_.force('link').links(links); this.restartSimulation_(); } @@ -932,6 +1070,12 @@ class Graph { .attr('x2', d => d.target.x) .attr('y2', d => d.target.y); + const dashedLines = this.dashedLinkGroup_.selectAll('line'); + dashedLines.attr('x1', d => d.source.x) + .attr('y1', d => d.source.y) + .attr('x2', d => d.target.x) + .attr('y2', d => d.target.y); + this.updateToolTipLinks(); } @@ -945,6 +1089,7 @@ class Graph { addNode_(node) { this.nodes_.set(node.id, node); this.addNodeLinks_(node); + this.addDashedNodeLinks_(node); node.setInitialPosition(this.width_, this.height_); } @@ -955,8 +1100,7 @@ class Graph { * @private */ addNodeLinks_(node) { - const linkTargets = node.linkTargets(); - for (const linkTarget of linkTargets) { + for (const linkTarget of node.linkTargets) { const target = this.nodes_.get(linkTarget); if (target) { this.links_.push({source: node, target: target}); @@ -965,6 +1109,21 @@ class Graph { } /** + * Adds all the dashed links for a node to the graph. + * + * @param {!GraphNode} node + * @private + */ + addDashedNodeLinks_(node) { + for (const dashedLinkTarget of node.dashedLinkTargets) { + const target = this.nodes_.get(dashedLinkTarget); + if (target) { + this.dashedLinks_.push({source: node, target: target}); + } + } + } + + /** * @param {!GraphNode} d The dragged node. * @private */ @@ -993,8 +1152,16 @@ class Graph { if (!d3.event.active) { this.simulation_.alphaTarget(0); } - d.fx = null; - d.fy = null; + // Leave the node pinned where it was dropped. Return it to free + // positioning if it's dropped outside its designated area. + const bounds = d.allowedYRange(this.height_); + if (d3.event.y < bounds[0] || d3.event.y > bounds[1]) { + d.fx = null; + d.fy = null; + } + + // Toggle the pinned class as appropriate for the circle backing this node. + d3.select(`#circle-${d.id}`).classed('pinned', d.fx != null); } /** @@ -1010,7 +1177,7 @@ class Graph { * @private */ getTargetYPositionStrength_(d) { - return d.targetYPositionStrength(); + return d.targetYPositionStrength; } /** @@ -1018,7 +1185,7 @@ class Graph { * @private */ getManyBodyStrength_(d) { - return d.manyBodyStrength(); + return d.manyBodyStrength; } /** @@ -1093,7 +1260,7 @@ class Graph { .strength(this.getTargetYPositionStrength_.bind(this)); this.simulation_.force('x_pos', xForce); this.simulation_.force('y_pos', yForce); - this.simulation_.force('y_bound', boundingForce(this.height_)); + this.simulation_.force('y_bound', boundingForce(this.height_, this.width_)); if (!this.wasResized_) { this.wasResized_ = true; diff --git a/chromium/chrome/browser/resources/discards/graph_doc_template.html b/chromium/chrome/browser/resources/discards/graph_doc_template.html index b9fdfb27c8d..bcdb842d0c0 100644 --- a/chromium/chrome/browser/resources/discards/graph_doc_template.html +++ b/chromium/chrome/browser/resources/discards/graph_doc_template.html @@ -21,6 +21,20 @@ URL. As result, this document needs to be self-contained, hence inline scripts. .links line { stroke: #999; stroke-opacity: 0.6; + stroke-width: 1; + } + + .dashed-links line { + marker-start: url(#arrowToSource); + stroke: #999; + stroke-dasharray: 3; + stroke-opacity: 0.6; + stroke-width: 1; + } + + #arrowToSource { + fill: #999; + stroke: #999; } .nodes circle { @@ -28,6 +42,10 @@ URL. As result, this document needs to be self-contained, hence inline scripts. stroke-width: 1.5px; } + .nodes circle.pinned { + stroke: red; + } + .dead image { display: none; } @@ -70,6 +88,13 @@ ${javascript_file} </head> <body> <div id="toolTips" width="100%" height="100%"></div> - <svg id="graphBody" width="100%" height="100%"></svg> + <svg id="graphBody" width="100%" height="100%"> + <defs> + <marker id="arrowToSource" viewBox="0 -5 10 10" refX="-12" refY="0" + markerWidth="9" markerHeight="6" orient="auto"> + <path d="M15,-7 L0,0 L15,7" /> + </marker> + </defs> + </svg> </body> </html> diff --git a/chromium/chrome/browser/resources/downloads/BUILD.gn b/chromium/chrome/browser/resources/downloads/BUILD.gn index b54a16fd160..905b771d0a8 100644 --- a/chromium/chrome/browser/resources/downloads/BUILD.gn +++ b/chromium/chrome/browser/resources/downloads/BUILD.gn @@ -32,6 +32,7 @@ if (optimize_webui) { unpak("unpak") { pak_file = downloads_pak_file out_folder = unpak_folder + excludes = [ "../../ui/webui/downloads/downloads.mojom-lite.js" ] deps = [ ":flattened_resources" ] } diff --git a/chromium/chrome/browser/resources/downloads/downloads.html b/chromium/chrome/browser/resources/downloads/downloads.html index c7ad2c10bc1..4e1efc9f67b 100644 --- a/chromium/chrome/browser/resources/downloads/downloads.html +++ b/chromium/chrome/browser/resources/downloads/downloads.html @@ -1,6 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" - $i18n{a11yenhanced}> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> <head> <meta charset="utf-8"> <base href="chrome://downloads"> diff --git a/chromium/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd b/chromium/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd index 70f3e213e2e..68cdc6946b9 100644 --- a/chromium/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd +++ b/chromium/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd @@ -21,18 +21,15 @@ <include name="IDR_DOWNLOADS_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\downloads\downloads.mojom-lite.js" use_base_dir="false" - compress="gzip" type="BINDATA" /> <include name="IDR_DOWNLOADS_DOWNLOADS_HTML" file="downloads.html" preprocess="true" - type="chrome_html" - compress="gzip" /> + type="chrome_html" /> <include name="IDR_DOWNLOADS_DOWNLOADS_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\downloads\downloads.rollup.js" use_base_dir="false" preprocess="true" - compress="gzip" type="BINDATA" /> </includes> </release> diff --git a/chromium/chrome/browser/resources/downloads/toolbar.html b/chromium/chrome/browser/resources/downloads/toolbar.html index 2220c953c17..b87845dcdde 100644 --- a/chromium/chrome/browser/resources/downloads/toolbar.html +++ b/chromium/chrome/browser/resources/downloads/toolbar.html @@ -10,7 +10,6 @@ } cr-icon-button { - --cr-icon-button-fill-color-focus: var(--cr-toolbar-background-color); justify-content: flex-end; margin: 4px; } diff --git a/chromium/chrome/browser/resources/extensions/BUILD.gn b/chromium/chrome/browser/resources/extensions/BUILD.gn index 6ad3d269eb8..53ed19cc2b6 100644 --- a/chromium/chrome/browser/resources/extensions/BUILD.gn +++ b/chromium/chrome/browser/resources/extensions/BUILD.gn @@ -378,12 +378,12 @@ js_library("service") { "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", ] - externs_list = [ - "$externs_path/activity_log_private.js", - "$externs_path/developer_private.js", - "$externs_path/management.js", - "$externs_path/metrics_private.js", - ] + externs_list = chrome_extension_public_externs + [ + "$externs_path/activity_log_private.js", + "$externs_path/developer_private.js", + "$externs_path/management.js", + "$externs_path/metrics_private.js", + ] } js_library("shortcut_input") { diff --git a/chromium/chrome/browser/resources/extensions/detail_view.html b/chromium/chrome/browser/resources/extensions/detail_view.html index 2e647218766..04c47dbf7cc 100644 --- a/chromium/chrome/browser/resources/extensions/detail_view.html +++ b/chromium/chrome/browser/resources/extensions/detail_view.html @@ -401,7 +401,7 @@ </div> </div> <cr-link-row class="hr" id="remove-extension" - hidden="[[isControlled_(data.controlledInfo)]]" + hidden="[[data.mustRemainInstalled]]" label="$i18n{itemRemoveExtension}" on-click="onRemoveTap_"> </cr-link-row> </div> diff --git a/chromium/chrome/browser/resources/extensions/detail_view.js b/chromium/chrome/browser/resources/extensions/detail_view.js index eb337947210..fc461db137c 100644 --- a/chromium/chrome/browser/resources/extensions/detail_view.js +++ b/chromium/chrome/browser/resources/extensions/detail_view.js @@ -31,7 +31,7 @@ import {afterNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/po import {ItemDelegate} from './item.js'; import {ItemBehavior} from './item_behavior.js'; -import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isControlled, isEnabled, userCanChangeEnablement} from './item_util.js'; +import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isEnabled, userCanChangeEnablement} from './item_util.js'; import {navigation, Page} from './navigation_helper.js'; Polymer({ @@ -132,14 +132,6 @@ Polymer({ * @return {boolean} * @private */ - isControlled_() { - return isControlled(this.data); - }, - - /** - * @return {boolean} - * @private - */ isEnabled_() { return isEnabled(this.data.state); }, @@ -321,8 +313,6 @@ Polymer({ switch (type) { case 'POLICY': return 'cr20:domain'; - case 'SUPERVISED_USER_CUSTODIAN': - return 'cr:supervisor-account'; default: return ''; } diff --git a/chromium/chrome/browser/resources/extensions/extensions.html b/chromium/chrome/browser/resources/extensions/extensions.html index 087a92fd887..c5980f41fd1 100644 --- a/chromium/chrome/browser/resources/extensions/extensions.html +++ b/chromium/chrome/browser/resources/extensions/extensions.html @@ -1,6 +1,6 @@ <!doctype html> <html dir="$i18n{textdirection}" lang="$i18n{language}" - class="loading $i18n{loadTimeClasses}" $i18n{a11yenhanced}> + class="loading $i18n{loadTimeClasses}"> <head> <meta charset="utf8"> <title>$i18n{title}</title> diff --git a/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd b/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd index 3ebe27cf553..6ef33b79788 100644 --- a/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd +++ b/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd @@ -14,22 +14,18 @@ <includes> <include name="IDR_EXTENSIONS_EXTENSIONS_HTML" file="extensions.html" - type="chrome_html" - compress="gzip" /> + type="chrome_html" /> <include name="IDR_EXTENSIONS_EXTENSIONS_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\extensions\extensions.rollup.js" use_base_dir="false" preprocess="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_EXTENSIONS_CHECKUP_IMAGE" file="checkup_image.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_EXTENSIONS_CHECKUP_IMAGE_DARK" file="checkup_image_dark.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/extensions/item.html b/chromium/chrome/browser/resources/extensions/item.html index 712997e330d..fb2f6d20bdb 100644 --- a/chromium/chrome/browser/resources/extensions/item.html +++ b/chromium/chrome/browser/resources/extensions/item.html @@ -279,7 +279,7 @@ </cr-button> <cr-button id="remove-button" on-click="onRemoveTap_" aria-describedby="a11yAssociation" - hidden="[[isControlled_(data.controlledInfo)]]"> + hidden="[[data.mustRemainInstalled]]"> $i18n{remove} </cr-button> <template is="dom-if" if="[[shouldShowErrorsButton_(data.*)]]"> diff --git a/chromium/chrome/browser/resources/extensions/item.js b/chromium/chrome/browser/resources/extensions/item.js index fb88800bb62..51eb641791c 100644 --- a/chromium/chrome/browser/resources/extensions/item.js +++ b/chromium/chrome/browser/resources/extensions/item.js @@ -27,7 +27,7 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {flush, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {ItemBehavior} from './item_behavior.js'; -import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isControlled, isEnabled, SourceType, userCanChangeEnablement} from './item_util.js'; +import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isEnabled, SourceType, userCanChangeEnablement} from './item_util.js'; import {navigation, Page} from './navigation_helper.js'; /** @interface */ @@ -276,14 +276,6 @@ Polymer({ * @return {boolean} * @private */ - isControlled_() { - return isControlled(this.data); - }, - - /** - * @return {boolean} - * @private - */ isEnabled_() { return isEnabled(this.data.state); }, diff --git a/chromium/chrome/browser/resources/extensions/item_util.js b/chromium/chrome/browser/resources/extensions/item_util.js index a1f91b53f7e..83e727c2641 100644 --- a/chromium/chrome/browser/resources/extensions/item_util.js +++ b/chromium/chrome/browser/resources/extensions/item_util.js @@ -44,14 +44,6 @@ export function isEnabled(state) { } /** - * @param {!chrome.developerPrivate.ExtensionInfo} extensionInfo - * @return {boolean} Whether the extension is controlled. - */ -export function isControlled(extensionInfo) { - return !!extensionInfo.controlledInfo; -} - -/** * Returns true if the user can change whether or not the extension is * enabled. * @param {!chrome.developerPrivate.ExtensionInfo} item diff --git a/chromium/chrome/browser/resources/feedback/html/default.html b/chromium/chrome/browser/resources/feedback/html/default.html index b7c50d54717..2cfa06d8d1a 100644 --- a/chromium/chrome/browser/resources/feedback/html/default.html +++ b/chromium/chrome/browser/resources/feedback/html/default.html @@ -1,24 +1,25 @@ <!doctype html> <html i18n-values="dir:textdirection;lang:language"> <head> -<meta charset="utf-8"> -<link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> -<link rel="stylesheet" href="chrome://resources/css/apps/common.css"></link> -<link rel="stylesheet" href="chrome://resources/css/apps/topbutton_bar.css"> -</link> -<link rel="stylesheet" href="../css/feedback.css"> + <title i18n-content="appTitle"> </title> + <meta charset="utf-8"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> + <link rel="stylesheet" href="chrome://resources/css/apps/common.css"></link> + <link rel="stylesheet" href="chrome://resources/css/apps/topbutton_bar.css"> + </link> + <link rel="stylesheet" href="../css/feedback.css"> -<script src="chrome://resources/js/load_time_data.js"></script> -<script src="chrome://resources/js/i18n_template_no_process.js"></script> -<script src="chrome://resources/js/util.js"></script> -<script src="../js/feedback_util.js"></script> -<script src="../js/take_screenshot.js"></script> -<script src="../js/topbar_handlers.js"></script> -<script src="../js/feedback.js"></script> + <script src="chrome://resources/js/load_time_data.js"></script> + <script src="chrome://resources/js/i18n_template_no_process.js"></script> + <script src="chrome://resources/js/util.js"></script> + <script src="../js/feedback_util.js"></script> + <script src="../js/take_screenshot.js"></script> + <script src="../js/topbar_handlers.js"></script> + <script src="../js/feedback.js"></script> </head> <body> <div id="title-bar" class="title-bar"> - <span id="page-title" i18n-content="page-title"></span> + <span id="page-title" i18n-content="pageTitle"></span> <span class="topbutton-bar"> <button class="minimize-button" id="minimize-button" tabindex="-1" i18n-values="aria-label:minimizeBtnLabel"> diff --git a/chromium/chrome/browser/resources/feedback/js/event_handler.js b/chromium/chrome/browser/resources/feedback/js/event_handler.js index 5f9b2397257..ac5f433853d 100644 --- a/chromium/chrome/browser/resources/feedback/js/event_handler.js +++ b/chromium/chrome/browser/resources/feedback/js/event_handler.js @@ -21,11 +21,12 @@ const FEEDBACK_HEIGHT = 610; */ const FEEDBACK_DEFAULT_WINDOW_ID = 'default_window'; +// List of extension IDs that are permitted to invoke Feedback. // To generate a hashed extension ID, use a sha-1 hash, all in lower case. // Example: // echo -n 'abcdefghijklmnopqrstuvwxyzabcdef' | sha1sum | \ // awk '{print toupper($1)}' -const whitelistedExtensionIds = [ +const feedbackCallerExtensions = [ '12E618C3C6E97495AAECF2AC12DEB082353241C6', // QuickOffice '3727DD3E564B6055387425027AD74C58784ACC15', // QuickOffice '2FC374607C2DF285634B67C64A2E356C607091C3', // QuickOffice @@ -221,16 +222,16 @@ class FeedbackRequest { } /** - * Function to determine whether or not a given extension id is whitelisted to - * invoke the feedback UI. If the extension is whitelisted, the callback to - * start the Feedback UI will be called. + * Function to determine whether or not a given extension id is allowed to + * invoke the feedback UI. If it is, the callback to start the Feedback UI will + * be called. * @param {string} id the id of the sender extension. * @param {Function} startFeedbackCallback The callback function that will * will start the feedback UI. * @param {Object} feedbackInfo The feedback info object to pass to the * start feedback UI callback. */ -function senderWhitelisted(id, startFeedbackCallback, feedbackInfo) { +function invokeFeedbackIfPermitted(id, startFeedbackCallback, feedbackInfo) { crypto.subtle.digest('SHA-1', new TextEncoder().encode(id)) .then(function(hashBuffer) { let hashString = ''; @@ -240,7 +241,7 @@ function senderWhitelisted(id, startFeedbackCallback, feedbackInfo) { hashString += n < 0x10 ? '0' : ''; hashString += n.toString(16); } - if (whitelistedExtensionIds.indexOf(hashString.toUpperCase()) != -1) { + if (feedbackCallerExtensions.indexOf(hashString.toUpperCase()) != -1) { startFeedbackCallback(feedbackInfo); } }); @@ -267,7 +268,7 @@ function feedbackReadyHandler(request, sender, sendResponse) { */ function requestFeedbackHandler(request, sender, sendResponse) { if (request.requestFeedback) { - senderWhitelisted(sender.id, startFeedbackUI, request.feedbackInfo); + invokeFeedbackIfPermitted(sender.id, startFeedbackUI, request.feedbackInfo); } } diff --git a/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js b/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js index a450e1d88e7..c641a0302dc 100644 --- a/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js +++ b/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js @@ -822,7 +822,7 @@ cr.define('cr.login', function() { } else if (headerName == LOCATION_HEADER) { // If the "choose what to sync" checkbox was clicked, then the // continue URL will contain a source=3 field. - assert(header.value); + assert(header.value !== undefined); const location = decodeURIComponent(header.value); this.chooseWhatToSync_ = !!location.match(/(\?|&)source=3($|&)/); } diff --git a/chromium/chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd b/chromium/chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd index 52a9c5a1e7a..8e82e1235ab 100644 --- a/chromium/chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd +++ b/chromium/chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd @@ -15,38 +15,31 @@ <include name="IDR_GAIA_AUTH_AUTHENTICATOR_M_JS" file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/authenticator.m.js" use_base_dir="false" - type ="BINDATA" - compress="gzip" /> + type ="BINDATA" /> <include name="IDR_GAIA_AUTH_SAML_HANDLER_M_JS" file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/saml_handler.m.js" use_base_dir="false" - type ="BINDATA" - compress="gzip" /> + type ="BINDATA" /> <include name="IDR_GAIA_AUTH_CHANNEL_M_JS" file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/channel.m.js" use_base_dir="false" - type ="BINDATA" - compress="gzip" /> + type ="BINDATA" /> <include name="IDR_GAIA_AUTH_POST_MESSAGE_CHANNEL_M_JS" file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/post_message_channel.m.js" use_base_dir="false" - type ="BINDATA" - compress="gzip" /> + type ="BINDATA" /> <include name="IDR_GAIA_AUTH_WEBVIEW_EVENT_MANAGER_M_JS" file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/webview_event_manager.m.js" use_base_dir="false" - type ="BINDATA" - compress="gzip" /> + type ="BINDATA" /> <include name="IDR_GAIA_AUTH_SAML_PASSWORD_ATTRIBUTES_M_JS" file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/saml_password_attributes.m.js" use_base_dir="false" - type ="BINDATA" - compress="gzip" /> + type ="BINDATA" /> <include name="IDR_GAIA_AUTH_SAML_TIMESTAMPS_M_JS" file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/saml_timestamps.m.js" use_base_dir="false" - type ="BINDATA" - compress="gzip" /> + type ="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js b/chromium/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js index 00f17b5dab6..286b664860b 100644 --- a/chromium/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js +++ b/chromium/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js @@ -16,6 +16,12 @@ cr.define('cr.samlPasswordChange', function() { const oktaInjectedScriptName = 'oktaInjected'; /** + * "SAML password change extension" which helps detect password change + * @type {string} + */ + const extensionId = 'mkmjngkgbjeljoblnahkagdlcdeiiped'; + + /** * The script to inject into Okta user settings page. * @type {string} */ @@ -25,9 +31,26 @@ cr.define('cr.samlPasswordChange', function() { const BLANK_PAGE_URL = 'about:blank'; + + /** + * @param {string} extensionId The ID of the extension to send the message to. + * @param {any} message The message to send. This message should be a + * JSON-ifiable object. + * @param {function} callback the response callback function + * @private + * @see: https://developer.chrome.com/extensions/runtime#method-sendMessage + */ + function sendMessage_(extensionId, message, callback) { + // Sending message to extension and callback will be used to receive + // response from extension. This way is used to send one time request : + // https://developer.chrome.com/extensions/messaging#simple + chrome.runtime.sendMessage(extensionId, message, callback); + } + /** * The different providers of password-change pages that we support, or are * working on supporting. + * Should match the enum in SAML password change extension * @enum {number} */ const PasswordChangePageProvider = { @@ -309,10 +332,28 @@ cr.define('cr.samlPasswordChange', function() { * @private */ onBeforeRedirect_(details) { - if (details.method == 'POST' && - detectPasswordChangeSuccess( - safeParseUrl_(details.url), safeParseUrl_(details.redirectUrl))) { - this.onPasswordChangeSuccess_(false /* isOkta != OKTA */); + if (details.method == 'POST') { + const message = { + name: 'detectPasswordChangeSuccess', + url: details.url, + redirectUrl: details.redirectUrl + }; + sendMessage_(extensionId, message, (passwordChangeSuccess) => { + // SAML change password extension will be used to detect the password + // change success from url passed. + // 'passwordChangeSuccess' will be equal to undefined in case + // extension isn't installed or disabled, In this case normal flow + // will be used. + // Otherwise 'passwordChangeSuccess' will indcate whether extension + // detected password change successfully. + if (passwordChangeSuccess || + (typeof passwordChangeSuccess === 'undefined' && + detectPasswordChangeSuccess( + safeParseUrl_(details.url), + safeParseUrl_(details.redirectUrl)))) { + this.onPasswordChangeSuccess_(false /* isOkta */); + } + }); } } @@ -339,10 +380,20 @@ cr.define('cr.samlPasswordChange', function() { */ onMessageReceived_(event) { if (event.data == 'passwordChangeSuccess') { - const pageProvider = detectProvider_(safeParseUrl_(event.origin)); - if (pageProvider == PasswordChangePageProvider.OKTA) { - this.onPasswordChangeSuccess_(true /* isOkta == OKTA */); - } + const message = {name: 'detectProvider', url: event.origin}; + sendMessage_(extensionId, message, (provider) => { + // SAML change password extension will be used to detect provider + // from url passed. + // 'provider' will be equal to undefined in case + // extension isn't installed or disabled, In this case normal flow + // will be used. + if (provider == PasswordChangePageProvider.OKTA || + (typeof provider === 'undefined' && + detectProvider_(safeParseUrl_(event.origin)) == + PasswordChangePageProvider.OKTA)) { + this.onPasswordChangeSuccess_(true /* isOkta */); + } + }); } } } diff --git a/chromium/chrome/browser/resources/history/history.html b/chromium/chrome/browser/resources/history/history.html index 506a68f4ff3..7f78155dfe5 100644 --- a/chromium/chrome/browser/resources/history/history.html +++ b/chromium/chrome/browser/resources/history/history.html @@ -1,5 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{a11yenhanced}> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <base href="chrome://history"> <meta charset="utf8"> diff --git a/chromium/chrome/browser/resources/history/history_resources_vulcanized.grd b/chromium/chrome/browser/resources/history/history_resources_vulcanized.grd index c602d28c9c9..8873cf877a2 100644 --- a/chromium/chrome/browser/resources/history/history_resources_vulcanized.grd +++ b/chromium/chrome/browser/resources/history/history_resources_vulcanized.grd @@ -15,33 +15,27 @@ <include name="IDR_HISTORY_HISTORY_HTML" file="history.html" preprocess="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_HISTORY_IMAGES_SIGN_IN_PROMO_DARK_SVG" file="images\sign_in_promo_dark.svg" - compress="gzip" type="BINDATA" /> <include name="IDR_HISTORY_IMAGES_SIGN_IN_PROMO_SVG" file="images\sign_in_promo.svg" - compress="gzip" type="BINDATA" /> <include name="IDR_HISTORY_HISTORY_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\history\history.rollup.js" preprocess="true" type="BINDATA" - compress="gzip" use_base_dir="false" /> <include name="IDR_HISTORY_LAZY_LOAD_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\history\lazy_load.rollup.js" preprocess="true" type="BINDATA" - compress="gzip" use_base_dir="false" /> <include name="IDR_HISTORY_SHARED_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\history\shared.rollup.js" preprocess="true" type="BINDATA" - compress="gzip" use_base_dir="false" /> </includes> </release> diff --git a/chromium/chrome/browser/resources/inline_login/inline_login.js b/chromium/chrome/browser/resources/inline_login/inline_login.js index 44635972745..a0988731025 100644 --- a/chromium/chrome/browser/resources/inline_login/inline_login.js +++ b/chromium/chrome/browser/resources/inline_login/inline_login.js @@ -65,9 +65,8 @@ cr.define('inline.login', function() { * Initialize the UI. */ function initialize() { - $('navigation-button').addEventListener('click', navigationButtonClicked); + $('navigation-button').addEventListener('click', navigateBackInWebview); cr.addWebUIListener('show-back-button', showBackButton); - cr.addWebUIListener('navigate-back-in-webview', navigateBackInWebview); cr.addWebUIListener('load-auth-extension', loadAuthExtension); cr.addWebUIListener('close-dialog', closeDialog); @@ -148,15 +147,12 @@ cr.define('inline.login', function() { function navigateBackInWebview() { if ($('signin-frame').canGoBack()) { $('signin-frame').back(); + $('signin-frame').focus(); } else { closeDialog(); } } - function navigationButtonClicked() { - chrome.send('navigationButtonClicked'); - } - return { closeDialog: closeDialog, sendLSTFetchResults: sendLSTFetchResults, @@ -165,7 +161,6 @@ cr.define('inline.login', function() { initialize: initialize, isAuthReady: isAuthReady, loadAuthExtension: loadAuthExtension, - navigationButtonClicked: navigationButtonClicked, showBackButton: showBackButton, }; }); diff --git a/chromium/chrome/browser/resources/internals/query_tiles/BUILD.gn b/chromium/chrome/browser/resources/internals/query_tiles/BUILD.gn new file mode 100644 index 00000000000..6d3f2cb3d6e --- /dev/null +++ b/chromium/chrome/browser/resources/internals/query_tiles/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") + +js_type_check("closure_compile") { + uses_js_modules = true + deps = [ + ":query_tiles_internals", + ":query_tiles_internals_browser_proxy", + ] +} + +js_library("query_tiles_internals") { + deps = [ + ":query_tiles_internals_browser_proxy", + "//ui/webui/resources/js:cr.m", + "//ui/webui/resources/js:util.m", + ] +} + +js_library("query_tiles_internals_browser_proxy") { + deps = [ "//ui/webui/resources/js:cr.m" ] +} diff --git a/chromium/chrome/browser/resources/internals/query_tiles/query_tiles_internals.html b/chromium/chrome/browser/resources/internals/query_tiles/query_tiles_internals.html new file mode 100644 index 00000000000..5b037055148 --- /dev/null +++ b/chromium/chrome/browser/resources/internals/query_tiles/query_tiles_internals.html @@ -0,0 +1,31 @@ +<!doctype html> +<html lang="en" dir="ltr"> + <head> + <meta charset="utf-8"> + <title>Query Tiles Internals</title> + <meta name="viewport" content="width=device-width"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> + </head> + <body> + <h1>Query Tiles Internals</h1> + <h4>Fetcher Controller</h4> + <div> + <button id="start-fetch">Start fetch</button> + </div> + <h4>Database Controller</h4> + <div> + <button id="purge-db">Purge database</button> + </div> + <h4>Service State</h4> + <div> + Fetcher status: <span id="fetcher-status"></span> + Database status: <span id="group-status"></span> + </div> + <h4>Tile data</h4> + Group info: <span id="group-info"></span> + Tile proto: <span id="tile-proto"></span> + <div> + </div> + <script type="module" src="query_tiles_internals.js"></script> + </body> +</html> diff --git a/chromium/chrome/browser/resources/internals/query_tiles/query_tiles_internals.js b/chromium/chrome/browser/resources/internals/query_tiles/query_tiles_internals.js new file mode 100644 index 00000000000..3bb73548dc2 --- /dev/null +++ b/chromium/chrome/browser/resources/internals/query_tiles/query_tiles_internals.js @@ -0,0 +1,49 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {$} from 'chrome://resources/js/util.m.js'; + +import {QueryTilesInternalsBrowserProxy, QueryTilesInternalsBrowserProxyImpl, ServiceStatus, TileData} from './query_tiles_internals_browser_proxy.js'; + +/** + * @param {!ServiceStatus} serviceStatus The current status of the tile + * service. + */ +function onServiceStatusChanged(serviceStatus) { + $('group-status').textContent = serviceStatus.groupStatus; + $('fetcher-status').textContent = serviceStatus.fetcherStatus; +} + +/** + * @param {!TileData} tileData The raw data persisted in database. + */ +function onTileDataAvailable(tileData) { + $('group-info').textContent = tileData.groupInfo; + $('tile-proto').textContent = tileData.tilesProto; +} + +function initialize() { + /** @type {!QueryTilesInternalsBrowserProxy} */ + const browserProxy = QueryTilesInternalsBrowserProxyImpl.getInstance(); + + // Register all event listeners. + addWebUIListener('service-status-changed', onServiceStatusChanged); + + addWebUIListener('tile-data-available', onTileDataAvailable); + + $('start-fetch').onclick = function() { + browserProxy.startFetch(); + }; + + $('purge-db').onclick = function() { + browserProxy.purgeDb(); + }; + + // Kick off requests for the current system state. + browserProxy.getServiceStatus().then(onServiceStatusChanged); + browserProxy.getTileData().then(onTileDataAvailable); +} + +document.addEventListener('DOMContentLoaded', initialize); diff --git a/chromium/chrome/browser/resources/internals/query_tiles/query_tiles_internals_browser_proxy.js b/chromium/chrome/browser/resources/internals/query_tiles/query_tiles_internals_browser_proxy.js new file mode 100644 index 00000000000..ded38b10374 --- /dev/null +++ b/chromium/chrome/browser/resources/internals/query_tiles/query_tiles_internals_browser_proxy.js @@ -0,0 +1,75 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js'; + +/** + * @typedef {{ + * fetcherStatus: string, + * groupStatus: string, + * }} + */ +export let ServiceStatus; + +/** + * @typedef {{ + * groupInfo: string, + * tilesProto: string, + * }} + */ +export let TileData; + +/** @interface */ +export class QueryTilesInternalsBrowserProxy { + /** + * Start fetch right now. + */ + startFetch() {} + + /** + * Delete everything in the database. + */ + purgeDb() {} + + /** + * Get the current status of the TileService. + * @return {!Promise<ServiceStatus>} A promise firing when the service + * status is fetched. + */ + getServiceStatus() {} + + /** + * Get raw data from TileService database. + * @return {!Promise<TileData>} A promise firing when the raw data + * is fetched. + */ + getTileData() {} +} + +/** + * @implements {QueryTilesInternalsBrowserProxy} + */ +export class QueryTilesInternalsBrowserProxyImpl { + /** @override */ + startFetch() { + return chrome.send('startFetch'); + } + + /** @override */ + purgeDb() { + return chrome.send('purgeDb'); + } + + /** @override */ + getServiceStatus() { + return sendWithPromise('getServiceStatus'); + } + + /** @override */ + getTileData() { + return sendWithPromise('getTileData'); + } +} + +addSingletonGetter(QueryTilesInternalsBrowserProxyImpl); diff --git a/chromium/chrome/browser/resources/interventions_internals/index.css b/chromium/chrome/browser/resources/interventions_internals/index.css index 1af46cd12f4..dec856074a3 100644 --- a/chromium/chrome/browser/resources/interventions_internals/index.css +++ b/chromium/chrome/browser/resources/interventions_internals/index.css @@ -26,7 +26,7 @@ body { } .previews-flag-value { - margin-left: 10px; + margin-inline-start: 10px; } button { @@ -138,7 +138,7 @@ table { td { border: 0; padding: 10px; - text-align: left; + text-align: start; vertical-align: middle; } @@ -205,14 +205,14 @@ td.log-url .url-tooltip::after { bottom: 100%; content: ' '; left: 50%; - margin-left: -5px; + margin-inline-start: -5px; position: absolute; } .expansion-row { background: transparent; border: 0; - margin-left: 20px; + margin-inline-start: 20px; padding: 0 0 0 15px; width: 80%; } @@ -268,7 +268,7 @@ tr.expansion-row td:nth-child(odd) { width: 60%; } - #blacklisted-hosts-table { + #blocklisted-hosts-table { width: 60%; } @@ -354,7 +354,7 @@ i { font-style: italic; } -#blacklist-ignored-status { +#blocklist-ignored-status { color: red; font-style: italic; font-weight: bold; diff --git a/chromium/chrome/browser/resources/interventions_internals/index.html b/chromium/chrome/browser/resources/interventions_internals/index.html index 4f171561365..dd5f3ad7a7d 100644 --- a/chromium/chrome/browser/resources/interventions_internals/index.html +++ b/chromium/chrome/browser/resources/interventions_internals/index.html @@ -26,8 +26,8 @@ <span>Logs</span> </label> <label class="inactive-tab"> - <input type="radio" id="blacklist-tab" name="tabs" - value="blacklist-status"> + <input type="radio" id="blocklist-tab" name="tabs" + value="blocklist-status"> <span>Blocklist Status</span> </label> <label class="inactive-tab"> @@ -74,26 +74,26 @@ </table> </div> - <div class="tab-content" id="blacklist-status"> - <div id="blacklist-ignored-status"></div> - <button id="ignore-blacklist-button" type="button"> + <div class="tab-content" id="blocklist-status"> + <div id="blocklist-ignored-status"></div> + <button id="ignore-blocklist-button" type="button"> Ignore Blocklist </button> - <div id="user-blacklisted-status"> + <div id="user-blocklisted-status"> User blocklisted status: - <span id="user-blacklisted-status-value">N/A</span> + <span id="user-blocklisted-status-value">N/A</span> </div> - <div id="blacklist-cleared-status"> + <div id="blocklist-cleared-status"> Last blocklist cleared: - <span id="blacklist-last-cleared-time">N/A</span> + <span id="blocklist-last-cleared-time">N/A</span> </div> - <div id="blacklisted-hosts"> + <div id="blocklisted-hosts"> <div class="table-name">Blocklisted hosts</div> - <table id="blacklisted-hosts-table"> + <table id="blocklisted-hosts-table"> <tr> - <th id="blacklisted-host-header">Host</th> - <th id="blacklisted-time-header">Time</th> + <th id="blocklisted-host-header">Host</th> + <th id="blocklisted-time-header">Time</th> </tr> </table> </div> diff --git a/chromium/chrome/browser/resources/interventions_internals/index.js b/chromium/chrome/browser/resources/interventions_internals/index.js index 752d3913dac..d88edff3bf0 100644 --- a/chromium/chrome/browser/resources/interventions_internals/index.js +++ b/chromium/chrome/browser/resources/interventions_internals/index.js @@ -3,9 +3,9 @@ // found in the LICENSE file. /** The columns that are used to find rows that contain the keyword. */ -const ENABLE_BLACKLIST_BUTTON = 'Enable Blacklist'; -const IGNORE_BLACKLIST_BUTTON = 'Ignore Blacklist'; -const IGNORE_BLACKLIST_MESSAGE = 'Blacklist decisions are ignored.'; +const ENABLE_BLOCKLIST_BUTTON = 'Enable Blocklist'; +const IGNORE_BLOCKLIST_BUTTON = 'Ignore Blocklist'; +const IGNORE_BLOCKLIST_MESSAGE = 'Blocklist decisions are ignored.'; const URL_THRESHOLD = 40; // Maximum URL length window.logTableMap = {}; @@ -469,59 +469,59 @@ InterventionsInternalPageImpl.prototype = { }, /** - * Update new blacklisted host to the web page. + * Update new blocklisted host to the web page. * * @override - * @param {!string} host The blacklisted host. - * @param {number} time The time when the host was blacklisted in milliseconds + * @param {!string} host The blocklisted host. + * @param {number} time The time when the host was blocklisted in milliseconds * since Unix epoch. */ - onBlacklistedHost(host, time) { + onBlocklistedHost(host, time) { const row = document.createElement('tr'); - row.setAttribute('class', 'blacklisted-host-row'); + row.setAttribute('class', 'blocklisted-host-row'); const hostTd = document.createElement('td'); - hostTd.setAttribute('class', 'host-blacklisted'); + hostTd.setAttribute('class', 'host-blocklisted'); hostTd.textContent = host; row.appendChild(hostTd); const timeTd = document.createElement('td'); - timeTd.setAttribute('class', 'host-blacklisted-time'); + timeTd.setAttribute('class', 'host-blocklisted-time'); timeTd.textContent = getTimeFormat(time); row.appendChild(timeTd); // TODO(thanhdle): Insert row at correct index. crbug.com/776105. - $('blacklisted-hosts-table').appendChild(row); + $('blocklisted-hosts-table').appendChild(row); }, /** - * Update to the page that the user blacklisted status has changed. + * Update to the page that the user blocklisted status has changed. * * @override - * @param {boolean} blacklisted The time of the event in milliseconds since + * @param {boolean} blocklisted The time of the event in milliseconds since * Unix epoch. */ - onUserBlacklistedStatusChange(blacklisted) { - const userBlacklistedStatus = $('user-blacklisted-status-value'); - userBlacklistedStatus.textContent = - (blacklisted ? 'Blacklisted' : 'Not blacklisted'); + onUserBlocklistedStatusChange(blocklisted) { + const userBlocklistedStatus = $('user-blocklisted-status-value'); + userBlocklistedStatus.textContent = + (blocklisted ? 'Blocklisted' : 'Not blocklisted'); }, /** - * Update the blacklist cleared status on the page. + * Update the blocklist cleared status on the page. * * @override * @param {number} time The time of the event in milliseconds since Unix * epoch. */ - onBlacklistCleared(time) { - const blacklistClearedStatus = $('blacklist-last-cleared-time'); - blacklistClearedStatus.textContent = getTimeFormat(time); + onBlocklistCleared(time) { + const blocklistClearedStatus = $('blocklist-last-cleared-time'); + blocklistClearedStatus.textContent = getTimeFormat(time); // Remove hosts from table. - const blacklistedHostsTable = $('blacklisted-hosts-table'); - for (let row = blacklistedHostsTable.rows.length - 1; row > 0; row--) { - blacklistedHostsTable.deleteRow(row); + const blocklistedHostsTable = $('blocklisted-hosts-table'); + for (let row = blocklistedHostsTable.rows.length - 1; row > 0; row--) { + blocklistedHostsTable.deleteRow(row); } // Remove log message from logs table. @@ -529,24 +529,24 @@ InterventionsInternalPageImpl.prototype = { // Log event message. insertMessageRowToMessageLogTable( - time, 'Blacklist', 'Blacklist Cleared', '' /* URL */, 0 /* pageId */); + time, 'Blocklist', 'Blocklist Cleared', '' /* URL */, 0 /* pageId */); }, /** - * Update the page with the new value of ignored blacklist decision status. + * Update the page with the new value of ignored blocklist decision status. * * @override - * @param {boolean} ignored The new status of whether the previews blacklist - * decisions is blacklisted or not. + * @param {boolean} ignored The new status of whether the previews blocklist + * decisions is blocklisted or not. */ - onIgnoreBlacklistDecisionStatusChanged(ignored) { - const ignoreButton = $('ignore-blacklist-button'); + onIgnoreBlocklistDecisionStatusChanged(ignored) { + const ignoreButton = $('ignore-blocklist-button'); ignoreButton.textContent = - ignored ? ENABLE_BLACKLIST_BUTTON : IGNORE_BLACKLIST_BUTTON; + ignored ? ENABLE_BLOCKLIST_BUTTON : IGNORE_BLOCKLIST_BUTTON; - // Update the status of blacklist ignored on the page. - $('blacklist-ignored-status').textContent = - ignored ? IGNORE_BLACKLIST_MESSAGE : ''; + // Update the status of blocklist ignored on the page. + $('blocklist-ignored-status').textContent = + ignored ? IGNORE_BLOCKLIST_MESSAGE : ''; }, /** @@ -601,12 +601,12 @@ cr.define('interventions_internals', () => { getPreviewsEnabled(); getPreviewsFlagsDetails(); - const ignoreButton = $('ignore-blacklist-button'); + const ignoreButton = $('ignore-blocklist-button'); ignoreButton.addEventListener('click', () => { - // Whether the blacklist is currently ignored. - const ignored = (ignoreButton.textContent == ENABLE_BLACKLIST_BUTTON); + // Whether the blocklist is currently ignored. + const ignored = (ignoreButton.textContent == ENABLE_BLOCKLIST_BUTTON); // Try to reverse the ignore status. - pageHandler.setIgnorePreviewsBlacklistDecision(!ignored); + pageHandler.setIgnorePreviewsBlocklistDecision(!ignored); }); } diff --git a/chromium/chrome/browser/resources/invalidations/about_invalidations.html b/chromium/chrome/browser/resources/invalidations/about_invalidations.html index d49aa981879..e15459fd78c 100644 --- a/chromium/chrome/browser/resources/invalidations/about_invalidations.html +++ b/chromium/chrome/browser/resources/invalidations/about_invalidations.html @@ -4,7 +4,6 @@ <meta charset="utf-8"> <title>Invalidations</title> <script src="chrome://resources/js/cr.js"></script> - <script src="chrome://resources/js/parse_html_subset.js"></script> <script src="chrome://resources/js/util.js"></script> <script src="chrome://invalidations/about_invalidations.js"></script> <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> diff --git a/chromium/chrome/browser/resources/invalidations/invalidations_resources.grd b/chromium/chrome/browser/resources/invalidations/invalidations_resources.grd index ee62de0daf7..8fdd278a0b7 100644 --- a/chromium/chrome/browser/resources/invalidations/invalidations_resources.grd +++ b/chromium/chrome/browser/resources/invalidations/invalidations_resources.grd @@ -8,9 +8,9 @@ </outputs> <release seq="1"> <includes> - <include name="IDR_ABOUT_INVALIDATIONS_HTML" file="about_invalidations.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> - <include name="IDR_ABOUT_INVALIDATIONS_JS" file="about_invalidations.js" type="BINDATA" compress="gzip" /> - <include name="IDR_ABOUT_INVALIDATIONS_CSS" file="about_invalidations.css" type="BINDATA" compress="gzip" /> + <include name="IDR_ABOUT_INVALIDATIONS_HTML" file="about_invalidations.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> + <include name="IDR_ABOUT_INVALIDATIONS_JS" file="about_invalidations.js" type="BINDATA" /> + <include name="IDR_ABOUT_INVALIDATIONS_CSS" file="about_invalidations.css" type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/local_ntp/externs.js b/chromium/chrome/browser/resources/local_ntp/externs.js index a23b3244f00..11ad0c32056 100644 --- a/chromium/chrome/browser/resources/local_ntp/externs.js +++ b/chromium/chrome/browser/resources/local_ntp/externs.js @@ -33,7 +33,6 @@ let MostVisitedData; * realboxEnabled: boolean, * realboxMatchOmniboxTheme: boolean, * richerPicker: boolean, - * suggestionTransparencyEnabled: boolean, * translatedStrings: Object<string>}} */ let configData; diff --git a/chromium/chrome/browser/resources/local_ntp/icons.grdp b/chromium/chrome/browser/resources/local_ntp/icons.grdp index 23d21d00472..b009d3e158e 100644 --- a/chromium/chrome/browser/resources/local_ntp/icons.grdp +++ b/chromium/chrome/browser/resources/local_ntp/icons.grdp @@ -1,31 +1,31 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> <include name="IDR_LOCAL_NTP_ICONS_BOOKMARK" - file="resources/local_ntp/icons/bookmark.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/bookmark.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_CALCULATOR" - file="resources/local_ntp/icons/calculator.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/calculator.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_CLOCK" - file="resources/local_ntp/icons/clock.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/clock.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_DRIVE_DOCS" - file="resources/local_ntp/icons/drive_docs.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/drive_docs.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_DRIVE_FOLDER" - file="resources/local_ntp/icons/drive_folder.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/drive_folder.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_DRIVE_FORM" - file="resources/local_ntp/icons/drive_form.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/drive_form.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_DRIVE_IMAGE" - file="resources/local_ntp/icons/drive_image.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/drive_image.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_DRIVE_LOGO" - file="resources/local_ntp/icons/drive_logo.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/drive_logo.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_DRIVE_PDF" - file="resources/local_ntp/icons/drive_pdf.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/drive_pdf.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_DRIVE_SHEETS" - file="resources/local_ntp/icons/drive_sheets.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/drive_sheets.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_DRIVE_SLIDES" - file="resources/local_ntp/icons/drive_slides.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/drive_slides.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_DRIVE_VIDEO" - file="resources/local_ntp/icons/drive_video.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/drive_video.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_EXTENSION_APP" - file="resources/local_ntp/icons/extension_app.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/extension_app.svg" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ICONS_PAGE" - file="resources/local_ntp/icons/page.svg" type="BINDATA" compress="gzip" /> + file="resources/local_ntp/icons/page.svg" type="BINDATA" /> </grit-part> diff --git a/chromium/chrome/browser/resources/local_ntp/local_ntp.js b/chromium/chrome/browser/resources/local_ntp/local_ntp.js index 15950635804..d9d58e1ddef 100644 --- a/chromium/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chromium/chrome/browser/resources/local_ntp/local_ntp.js @@ -1686,29 +1686,25 @@ function renderAutocompleteMatches(matches, suggestionGroupsMap) { * @param {!function()} callback */ function createActionButton(callback) { - const icon = document.createElement('button'); + const icon = document.createElement('div'); icon.classList.add(CLASSES.REMOVE_ICON); - icon.tabIndex = -1; - icon.onmousedown = e => { + const action = document.createElement('button'); + action.classList.add(CLASSES.REMOVE_MATCH); + action.appendChild(icon); + action.onmousedown = e => { e.preventDefault(); // Stops default browser action (focus) }; - icon.onauxclick = e => { + action.onauxclick = e => { if (e.button == 1) { // Middle click on delete should just noop for now (matches omnibox). e.preventDefault(); } }; - icon.onclick = e => { + action.onclick = e => { callback(); e.preventDefault(); // Stops default browser action (navigation) }; - const action = document.createElement('div'); - - action.classList.add(CLASSES.REMOVE_MATCH); - action.tabIndex = 0; - action.setAttribute('role', 'button'); - action.appendChild(icon); return action; } @@ -1747,18 +1743,18 @@ function renderAutocompleteMatches(matches, suggestionGroupsMap) { // preventing the popup from losing focus and closing as a result. headerEl.tabIndex = -1; headerEl.append(document.createTextNode(suggestionGroup.header)); - if (configData.suggestionTransparencyEnabled) { - const toggle = createActionButton(() => { - groupEl.classList.toggle(CLASSES.COLLAPSED); - updateToggleButtonA11y( - toggle, groupEl.classList.contains(CLASSES.COLLAPSED)); - window.chrome.embeddedSearch.searchBox - .toggleSuggestionGroupIdVisibility(suggestionGroupId); - }); - updateToggleButtonA11y(toggle, suggestionGroup.hidden); - headerEl.appendChild(toggle); - realboxMatchesEl.classList.add(CLASSES.REMOVABLE); - } + + const toggle = createActionButton(() => { + groupEl.classList.toggle(CLASSES.COLLAPSED); + updateToggleButtonA11y( + toggle, groupEl.classList.contains(CLASSES.COLLAPSED)); + window.chrome.embeddedSearch.searchBox.toggleSuggestionGroupIdVisibility( + suggestionGroupId); + }); + updateToggleButtonA11y(toggle, suggestionGroup.hidden); + headerEl.appendChild(toggle); + realboxMatchesEl.classList.add(CLASSES.REMOVABLE); + groupEl.appendChild(headerEl); realboxMatchesEl.appendChild(groupEl); suggestionGroupElsMap[suggestionGroupId] = groupEl; @@ -1852,7 +1848,7 @@ function renderAutocompleteMatches(matches, suggestionGroupsMap) { } } - if (match.supportsDeletion && configData.suggestionTransparencyEnabled) { + if (match.supportsDeletion) { const remove = createActionButton(() => { window.chrome.embeddedSearch.searchBox.deleteAutocompleteMatch(i); }); diff --git a/chromium/chrome/browser/resources/local_ntp/voice.js b/chromium/chrome/browser/resources/local_ntp/voice.js index bb8ce4fa6b6..7d88c54feb2 100644 --- a/chromium/chrome/browser/resources/local_ntp/voice.js +++ b/chromium/chrome/browser/resources/local_ntp/voice.js @@ -31,7 +31,7 @@ function getChromeUILanguage() { */ const LOG_TYPE = { // Activated by clicking on the fakebox icon. - ACTION_ACTIVATE_FAKEBOX: 13, + ACTION_ACTIVATE_SEARCH_BOX: 13, // Activated by keyboard shortcut. ACTION_ACTIVATE_KEYBOARD: 14, // Close the voice overlay by a user's explicit action. @@ -308,7 +308,7 @@ speech.init = function( fakeboxMicrophoneElem.onclick = function(event) { // If propagated, closes the overlay (click on the background). event.stopPropagation(); - speech.logEvent(LOG_TYPE.ACTION_ACTIVATE_FAKEBOX); + speech.logEvent(LOG_TYPE.ACTION_ACTIVATE_SEARCH_BOX); speech.start(); }; fakeboxMicrophoneElem.onkeydown = function(event) { diff --git a/chromium/chrome/browser/resources/management/management_browser_proxy.js b/chromium/chrome/browser/resources/management/management_browser_proxy.js index cf4a5a30586..4510d679e01 100644 --- a/chromium/chrome/browser/resources/management/management_browser_proxy.js +++ b/chromium/chrome/browser/resources/management/management_browser_proxy.js @@ -69,6 +69,7 @@ export const DeviceReportingType = { STATISTIC: 'device statistics', DEVICE: 'device', CRASH_REPORT: 'crash report', + APP_INFO_AND_ACTIVITY: 'app info and activity', LOGS: 'logs', PRINT: 'print', CROSTINI: 'crostini', diff --git a/chromium/chrome/browser/resources/management/management_ui.html b/chromium/chrome/browser/resources/management/management_ui.html index 0cb46863ce2..f2f414ce0e3 100644 --- a/chromium/chrome/browser/resources/management/management_ui.html +++ b/chromium/chrome/browser/resources/management/management_ui.html @@ -195,9 +195,9 @@ </div> <table class="content-indented"> <tr> - <th class="protection-name">$i18n{extensionName}</th> + <th class="protection-name">$i18n{connectorEvent}</th> <th class="protection-permissions"> - $i18n{extensionPermissions} + $i18n{connectorVisibleData} </th> </tr> <template is="dom-repeat" diff --git a/chromium/chrome/browser/resources/management/management_ui.js b/chromium/chrome/browser/resources/management/management_ui.js index 765261447a9..b928315c798 100644 --- a/chromium/chrome/browser/resources/management/management_ui.js +++ b/chromium/chrome/browser/resources/management/management_ui.js @@ -221,6 +221,8 @@ Polymer({ return 'cr:computer'; case DeviceReportingType.CRASH_REPORT: return 'management:crash'; + case DeviceReportingType.APP_INFO_AND_ACTIVITY: + return 'management:timelapse'; case DeviceReportingType.LOGS: return 'management:report'; case DeviceReportingType.PRINT: diff --git a/chromium/chrome/browser/resources/media/media_data_table.js b/chromium/chrome/browser/resources/media/media_data_table.js index 758ace61120..96e21e7f814 100644 --- a/chromium/chrome/browser/resources/media/media_data_table.js +++ b/chromium/chrome/browser/resources/media/media_data_table.js @@ -44,7 +44,7 @@ cr.define('cr.ui', function() { render() { // Find the body of the table and clear it. const body = this.table_.querySelectorAll('tbody')[0]; - body.innerHTML = ''; + body.innerHTML = trustedTypes.emptyHTML; // Get the sort key from the columns to determine which data should be in // which column. diff --git a/chromium/chrome/browser/resources/media/media_feeds.html b/chromium/chrome/browser/resources/media/media_feeds.html index 74429bf95b2..e6919df0c4b 100644 --- a/chromium/chrome/browser/resources/media/media_feeds.html +++ b/chromium/chrome/browser/resources/media/media_feeds.html @@ -80,6 +80,10 @@ content: '▼'; position: absolute; } + + div#fetch-logs-content { + color: red; + } </style> </head> <body> @@ -147,8 +151,11 @@ <th sort-key="resetReason"> Reset Reason </th> - <th data-key="associatedOrigins"> - Associated Origins + <th data-key="cookieNameFilter"> + Cookie Name Filter + </th> + <th data-key="safeSearchResult"> + Safe Search Result </th> <th data-key="logos"> Logos @@ -233,6 +240,10 @@ <tbody> </tbody> </table> + <div id="fetch-logs"> + <h3>Fetch logs:</h3> + <div id="fetch-logs-content"></div> + </div> </div> </body> </html> diff --git a/chromium/chrome/browser/resources/media/media_feeds.js b/chromium/chrome/browser/resources/media/media_feeds.js index 8ec4bee66af..09dd402294b 100644 --- a/chromium/chrome/browser/resources/media/media_feeds.js +++ b/chromium/chrome/browser/resources/media/media_feeds.js @@ -21,9 +21,16 @@ function whenConfigTableIsPopulatedForTest() { return mediaFeedsConfigTableIsPopulatedResolver.promise; } -const mediaFeedsConfigTableIsUpdatedResolver = new PromiseResolver(); -function whenConfigTableIsUpdatedForTest() { - return mediaFeedsConfigTableIsUpdatedResolver.promise; +const mediaFeedsConfigTableSafeSearchPrefIsUpdatedResolver = + new PromiseResolver(); +function whenConfigTableSafeSearchPrefIsUpdatedForTest() { + return mediaFeedsConfigTableSafeSearchPrefIsUpdatedResolver.promise; +} + +const mediaFeedsConfigTableBackgroundFetchingPrefIsUpdatedResolver = + new PromiseResolver(); +function whenConfigTableBackgroundFetchingPrefIsUpdatedForTest() { + return mediaFeedsConfigTableBackgroundFetchingPrefIsUpdatedResolver.promise; } (function() { @@ -53,6 +60,10 @@ class MediaFeedsTableDelegate { a.addEventListener('click', () => { showFeedContents(dataRow); + + // Clear old logs and hide the area from display. + $('fetch-logs').style.display = 'none'; + $('fetch-logs-content').textContent = ''; }); td.appendChild(document.createElement('br')); @@ -66,6 +77,9 @@ class MediaFeedsTableDelegate { store.fetchMediaFeed(dataRow.id).then(response => { updateFeedsTable(); showFeedContents(dataRow); + + $('fetch-logs').style.display = 'block'; + $('fetch-logs-content').textContent = response.logs; }); }); } @@ -155,7 +169,20 @@ class MediaFeedsTableDelegate { td.textContent = 'Movie'; break; } - } else if (key == 'isFamilyFriendly' || key == 'clicked') { + } else if (key == 'isFamilyFriendly') { + // Format a IsFamilyFriendly. + switch (parseInt(data, 10)) { + case mediaFeeds.mojom.IsFamilyFriendly.kUnknown: + td.textContent = 'Unknown'; + break; + case mediaFeeds.mojom.IsFamilyFriendly.kYes: + td.textContent = 'Yes'; + break; + case mediaFeeds.mojom.IsFamilyFriendly.kNo: + td.textContent = 'No'; + break; + } + } else if (key == 'clicked') { // Format a boolean. td.textContent = data ? 'Yes' : 'No'; } else if (key == 'actionStatus') { @@ -291,16 +318,6 @@ class MediaFeedsTableDelegate { td.textContent = 'Cache'; break; } - } else if (key === 'associatedOrigins') { - // Format the array of origins. - const origins = []; - - data.forEach((origin) => { - const {scheme, host, port} = origin; - origins.push(new URL(`${scheme}://${host}:${port}`).origin); - }); - - td.textContent = origins.join(', '); } else if (key === 'userIdentifier') { if (data) { td.textContent = 'Name=' + data.name; @@ -338,7 +355,7 @@ class MediaFeedsTableDelegate { sortKey === 'fetchFailedCount' || sortKey === 'lastFetchItemCount' || sortKey === 'lastFetchPlayNextCount' || sortKey === 'lastFetchContentTypes' || sortKey === 'safeSearchResult' || - sortKey === 'type') { + sortKey === 'type' || sortKey === 'cookieNameFilter') { return val1 > val2 ? 1 : -1; } else if ( sortKey === 'lastDiscoveryTime' || sortKey === 'lastFetchTime' || @@ -541,7 +558,7 @@ function createConfigRowWithToggle(name, value, clickAction) { * @param {!mediaFeeds.mojom.DebugInformation} info The debug info */ function renderConfigTable(info) { - configTableBody.innerHTML = ''; + configTableBody.innerHTML = trustedTypes.emptyHTML; configTableBody.appendChild(createConfigRow( 'Safe Search Enabled (value)', @@ -552,9 +569,26 @@ function renderConfigTable(info) { () => { store.setSafeSearchEnabledPref(!info.safeSearchPrefValue).then(() => { updateConfigTable().then( - () => mediaFeedsConfigTableIsUpdatedResolver.resolve()); + () => mediaFeedsConfigTableSafeSearchPrefIsUpdatedResolver + .resolve()); }); })); + + configTableBody.appendChild(createConfigRow( + 'Background Fetching Enabled (value)', + formatFeatureFlag(info.backgroundFetchingFeatureEnabled))); + + configTableBody.appendChild(createConfigRowWithToggle( + 'Background Fetching Enabled (pref)', + formatFeatureFlag(info.backgroundFetchingPrefValue), () => { + store.setBackgroundFetchingPref(!info.backgroundFetchingPrefValue) + .then(() => { + updateConfigTable().then( + () => + mediaFeedsConfigTableBackgroundFetchingPrefIsUpdatedResolver + .resolve()); + }); + })); } /** diff --git a/chromium/chrome/browser/resources/media/media_history.js b/chromium/chrome/browser/resources/media/media_history.js index 30c66de2df0..a0c2ad69f57 100644 --- a/chromium/chrome/browser/resources/media/media_history.js +++ b/chromium/chrome/browser/resources/media/media_history.js @@ -160,7 +160,7 @@ function decodeString16(arr) { * History store. */ function renderStatsTable(stats) { - statsTableBody.innerHTML = ''; + statsTableBody.innerHTML = trustedTypes.emptyHTML; Object.keys(stats.tableRowCounts).forEach((key) => { statsTableBody.appendChild(createStatsRow(key, stats.tableRowCounts[key])); diff --git a/chromium/chrome/browser/resources/media/webrtc_logs_resources.grd b/chromium/chrome/browser/resources/media/webrtc_logs_resources.grd index d4620a3d4ad..030e50ffc1b 100644 --- a/chromium/chrome/browser/resources/media/webrtc_logs_resources.grd +++ b/chromium/chrome/browser/resources/media/webrtc_logs_resources.grd @@ -14,12 +14,10 @@ file="webrtc_logs.html" flattenhtml="true" allowexternalscript="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_WEBRTC_LOGS_JS" file="webrtc_logs.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/nearby_internals/BUILD.gn b/chromium/chrome/browser/resources/nearby_internals/BUILD.gn new file mode 100644 index 00000000000..71c035040b5 --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_internals/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ ":nearby_internals" ] +} + +js_library("nearby_internals") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} + +html_to_js("web_components") { + js_files = [ "nearby_internals.js" ] +} diff --git a/chromium/chrome/browser/resources/nearby_internals/OWNERS b/chromium/chrome/browser/resources/nearby_internals/OWNERS new file mode 100644 index 00000000000..19414dc942a --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_internals/OWNERS @@ -0,0 +1,4 @@ +file://chrome/browser/nearby_sharing/OWNERS +khorimoto@chromium.org + +# COMPONENT: OS>Systems>Multidevice>Nearby diff --git a/chromium/chrome/browser/resources/nearby_internals/index.html b/chromium/chrome/browser/resources/nearby_internals/index.html new file mode 100644 index 00000000000..eb4fd150fc2 --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_internals/index.html @@ -0,0 +1,17 @@ +<!doctype html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> + <head> + <meta charset="utf-8"> + <base href="chrome://nearby-internals"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> + <style> + body { + margin: 0; + } + </style> + </head> + <body> + <nearby-internals></nearby-internals> + <script type="module" src="nearby_internals.js"></script> + </body> +</html> diff --git a/chromium/chrome/browser/resources/nearby_internals/nearby_internals.html b/chromium/chrome/browser/resources/nearby_internals/nearby_internals.html new file mode 100644 index 00000000000..ff39aaf9aee --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_internals/nearby_internals.html @@ -0,0 +1 @@ +<h1>Hello, world!!</h1> diff --git a/chromium/chrome/browser/resources/nearby_internals/nearby_internals.js b/chromium/chrome/browser/resources/nearby_internals/nearby_internals.js new file mode 100644 index 00000000000..a7f1da3568b --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_internals/nearby_internals.js @@ -0,0 +1,11 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +Polymer({ + is: 'nearby-internals', + + _template: html`{__html_template__}`, +}); diff --git a/chromium/chrome/browser/resources/nearby_internals/nearby_internals_resources.grd b/chromium/chrome/browser/resources/nearby_internals/nearby_internals_resources.grd new file mode 100644 index 00000000000..d7477df60d6 --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_internals/nearby_internals_resources.grd @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/nearby_internals_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/nearby_internals_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/nearby_internals_resources_map.h" + type="resource_map_header" /> + <output filename="nearby_internals_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <include name="IDR_NEARBY_INTERNALS_INDEX_HTML" + file="index.html" + type="BINDATA"/> + <include name="IDR_NEARBY_INTERNALS_NEARBY_INTERNALS_JS" + file="${root_gen_dir}\chrome\browser\resources\nearby_internals\nearby_internals.js" + use_base_dir="false" + type="BINDATA"/> + </includes> + </release> +</grit> diff --git a/chromium/chrome/browser/resources/nearby_share/BUILD.gn b/chromium/chrome/browser/resources/nearby_share/BUILD.gn new file mode 100644 index 00000000000..543394e5aaf --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_share/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ + ":app", + ":nearby_discovery_page", + ] +} + +js_library("app") { + deps = [ + ":nearby_discovery_page", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager.m", + ] +} + +js_library("nearby_discovery_page") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} + +html_to_js("web_components") { + js_files = [ + "app.js", + "nearby_discovery_page.js", + ] +} diff --git a/chromium/chrome/browser/resources/nearby_share/OWNERS b/chromium/chrome/browser/resources/nearby_share/OWNERS new file mode 100644 index 00000000000..72feb28bcca --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_share/OWNERS @@ -0,0 +1,3 @@ +file://chrome/browser/nearby_sharing/OWNERS + +# COMPONENT: UI>Browser>Sharing>Nearby diff --git a/chromium/chrome/browser/resources/nearby_share/app.html b/chromium/chrome/browser/resources/nearby_share/app.html new file mode 100644 index 00000000000..e16336c4164 --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_share/app.html @@ -0,0 +1,4 @@ +<cr-view-manager id="viewManager"> + <nearby-discovery-page id="[[Page.DISCOVERY]]" slot="view" class="active"> + </nearby-discovery-page> +</cr-view-manager> diff --git a/chromium/chrome/browser/resources/nearby_share/app.js b/chromium/chrome/browser/resources/nearby_share/app.js new file mode 100644 index 00000000000..fc77eb7ac2a --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_share/app.js @@ -0,0 +1,34 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview The 'nearby-share' component is the entry point for the Nearby + * Share flow. It is used as a standalone dialog via chrome://nearby and as part + * of the ChromeOS share sheet. + */ + +import 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.m.js'; +import './nearby_discovery_page.js'; +import './strings.m.js'; + +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +/** @enum {string} */ +const Page = { + DISCOVERY: 'discovery', +}; + +Polymer({ + is: 'nearby-share-app', + + _template: html`{__html_template__}`, + + properties: { + /** Mirroring the enum so that it can be used from HTML bindings. */ + Page: { + type: Object, + value: Page, + }, + }, +}); diff --git a/chromium/chrome/browser/resources/nearby_share/nearby_discovery_page.html b/chromium/chrome/browser/resources/nearby_share/nearby_discovery_page.html new file mode 100644 index 00000000000..cea179efa55 --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_share/nearby_discovery_page.html @@ -0,0 +1 @@ +<h1>Nearby Discovery Page</h1> diff --git a/chromium/chrome/browser/resources/nearby_share/nearby_discovery_page.js b/chromium/chrome/browser/resources/nearby_share/nearby_discovery_page.js new file mode 100644 index 00000000000..9b3308669a4 --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_share/nearby_discovery_page.js @@ -0,0 +1,16 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview The 'nearby-discovery-page' component shows the discovery UI of + * the Nearby Share flow. It shows a list of devices to select from. + */ + +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +Polymer({ + is: 'nearby-discovery-page', + + _template: html`{__html_template__}`, +}); diff --git a/chromium/chrome/browser/resources/nearby_share/nearby_share_dialog.html b/chromium/chrome/browser/resources/nearby_share/nearby_share_dialog.html new file mode 100644 index 00000000000..0417789bc2f --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_share/nearby_share_dialog.html @@ -0,0 +1,17 @@ +<!doctype html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> + <head> + <meta charset="utf-8"> + <base href="chrome://nearby"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> + <style> + body { + margin: 0; + } + </style> + </head> + <body> + <nearby-share-app></nearby-share-app> + <script type="module" src="app.js"></script> + </body> +</html> diff --git a/chromium/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd b/chromium/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd new file mode 100644 index 00000000000..96a629ef628 --- /dev/null +++ b/chromium/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/nearby_share_dialog_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/nearby_share_dialog_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/nearby_share_dialog_resources_map.h" + type="resource_map_header" /> + <output filename="nearby_share_dialog_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <include name="IDR_NEARBY_SHARE_NEARBY_SHARE_DIALOG_HTML" + file="nearby_share_dialog.html" + type="BINDATA"/> + + <!-- Generated Polymer 3 elements --> + <include name="IDR_NEARBY_SHARE_APP_JS" + file="${root_gen_dir}/chrome/browser/resources/nearby_share/app.js" + use_base_dir="false" type="BINDATA"/> + <include name="IDR_NEARBY_SHARE_NEARBY_DISCOVERY_PAGE_JS" + file="${root_gen_dir}/chrome/browser/resources/nearby_share/nearby_discovery_page.js" + use_base_dir="false" type="BINDATA"/> + </includes> + </release> +</grit> diff --git a/chromium/chrome/browser/resources/net_internals/browser_bridge.js b/chromium/chrome/browser/resources/net_internals/browser_bridge.js index fac5fb1d4d1..5c26ac203d6 100644 --- a/chromium/chrome/browser/resources/net_internals/browser_bridge.js +++ b/chromium/chrome/browser/resources/net_internals/browser_bridge.js @@ -18,8 +18,6 @@ const BrowserBridge = (function() { // List of observers for various bits of browser state. this.hstsObservers_ = []; this.expectCTObservers_ = []; - this.crosONCFileParseObservers_ = []; - this.storeDebugLogsObservers_ = []; this.setNetworkDebugModeObservers_ = []; } @@ -89,22 +87,6 @@ const BrowserBridge = (function() { this.send('flushSocketPools'); }, - importONCFile(fileContent, passcode) { - this.send('importONCFile', [fileContent, passcode]); - }, - - storeDebugLogs() { - this.send('storeDebugLogs'); - }, - - storeCombinedDebugLogs() { - this.send('storeCombinedDebugLogs'); - }, - - storeFeedbackSystemLogs() { - this.send('storeFeedbackSystemLogs'); - }, - setNetworkDebugMode(subsystem) { this.send('setNetworkDebugMode', [subsystem]); }, @@ -135,30 +117,6 @@ const BrowserBridge = (function() { } }, - receivedONCFileParse(error) { - for (let i = 0; i < this.crosONCFileParseObservers_.length; i++) { - this.crosONCFileParseObservers_[i].onONCFileParse(error); - } - }, - - receivedStoreDebugLogs(status) { - for (let i = 0; i < this.storeDebugLogsObservers_.length; i++) { - this.storeDebugLogsObservers_[i].onStoreDebugLogs(status); - } - }, - - receivedStoreCombinedDebugLogs(status) { - for (let i = 0; i < this.storeDebugLogsObservers_.length; i++) { - this.storeDebugLogsObservers_[i].onStoreCombinedDebugLogs(status); - } - }, - - receivedStoreFeedbackSystemLogs(status) { - for (let i = 0; i < this.storeDebugLogsObservers_.length; i++) { - this.storeDebugLogsObservers_[i].onStoreFeedbackSystemLogs(status); - } - }, - receivedSetNetworkDebugMode(status) { for (let i = 0; i < this.setNetworkDebugModeObservers_.length; i++) { this.setNetworkDebugModeObservers_[i].onSetNetworkDebugMode(status); @@ -188,27 +146,6 @@ const BrowserBridge = (function() { }, /** - * Adds a listener for ONC file parse status. The observer will be called - * back with: - * - * observer.onONCFileParse(error); - */ - addCrosONCFileParseObserver(observer) { - this.crosONCFileParseObservers_.push(observer); - }, - - /** - * Adds a listener for storing log file status. The observer will be called - * back with: - * - * observer.onStoreDebugLogs(status); - * observer.onStoreCombinedDebugLogs(status); - */ - addStoreDebugLogsObserver(observer) { - this.storeDebugLogsObservers_.push(observer); - }, - - /** * Adds a listener for network debugging mode status. The observer * will be called back with: * diff --git a/chromium/chrome/browser/resources/net_internals/chromeos_view.html b/chromium/chrome/browser/resources/net_internals/chromeos_view.html index ac4ae56ec08..71c81564e28 100644 --- a/chromium/chrome/browser/resources/net_internals/chromeos_view.html +++ b/chromium/chrome/browser/resources/net_internals/chromeos_view.html @@ -1,76 +1,19 @@ <div id="chromeos-view-tab-content" class=content-box> <h4 style='margin-top:0'>Import ONC file</h4> - <div id="chromeos-view-import-div"> - <label>Import ONC File - <input type="file" id="chromeos-view-import-onc"> - </label> + <div> + Import ONC File has moved to + <a href="chrome://network#general">chrome://network#general</a>. </div> - <div id="chromeos-view-password-div" hidden> - This onc file appears to be encrypted. Please provide the decryption key: - <div> - <input type="password" id="chromeos-view-onc-password"> - </div> + + <h4>Store system logs</h4> + <div> + Store system logs has moved to + <a href="chrome://network#logs">chrome://network#logs</a>. </div> - <div id="chromeos-view-parse-status" hidden> - </div> - <div id="chromeos-view-store-debug-logs-div"> - <h4>Store system logs</h4> - <div> - <p>This stores system_logs_{date}-{time}.txt.zip to the Downloads - directory. The archive contains a single file identical to the - system_logs file attached to Feedback reports.</p> - <p>Also writes a policies_{date}-{time}.json file for providing policy - configurations when that might be a factor.</p> - <p>Prefer this when uploading logs to issues or sending logs to developers - (unless otherwise requested).</p> - <input type="button" - id="chromeos-view-store-feedback-system-logs" - value="Store Feedback Report System Logs"> - <label id="chromeos-view-store-feedback-system-logs-status"></label> - </div> - <h4>Store debugd system logs</h4> - <div> - <p>This stores the logs collected by debugd as individual files in a - single archive file in the Downloads directory: - debug-logs_{date}-{time}.tgz. - </p> - <p>Also writes a policies_{date}-{time}.json file for providing policy - configurations when that might be a factor.</p> - <input type="button" - id="chromeos-view-store-debug-logs" - value="Store System Logs"> - <label id="chromeos-view-store-debug-logs-status"></label> - </div> - <div> - <p>Identical to the above, but also incldes the Chrome user logs. - The output file is named combined-logs_{date}-{time}.tgz.</p> - <input type="button" - id="chromeos-view-store-combined-debug-logs" - value="Store System and User Logs"> - <label id="chromeos-view-store-combined-debug-logs-status"></label> - </div> - </div> - <div id="chromeos-view-network-debugging-div"> - <h4>Network Debugging</h4> - <dl> - <dt>Select interface for debugging</dt> - <dd> - <input type="button" - value="Wi-Fi" - id="chromeos-view-network-debugging-wifi"> - <input type="button" - value="Ethernet" - id="chromeos-view-network-debugging-ethernet"> - <input type="button" - value="Cellular" - id="chromeos-view-network-debugging-cellular"> - <input type="button" - name="subsystem" - value="None" - id="chromeos-view-network-debugging-none"> - </dd> - </dl> - <label id="chromeos-view-network-debugging-status"> - </label> + + <h4>Network Debugging</h4> + <div> + Network Debugging has moved to + <a href="chrome://network#logs">chrome://network#logs</a>. </div> </div> diff --git a/chromium/chrome/browser/resources/net_internals/chromeos_view.js b/chromium/chrome/browser/resources/net_internals/chromeos_view.js index 07022b53664..253465ccd60 100644 --- a/chromium/chrome/browser/resources/net_internals/chromeos_view.js +++ b/chromium/chrome/browser/resources/net_internals/chromeos_view.js @@ -8,225 +8,6 @@ const CrosView = (function() { 'use strict'; - let fileContent; - let passcode = ''; - - /** - * Clear file input div - * - * @private - */ - function clearFileInput_() { - $(CrosView.IMPORT_DIV_ID).innerHTML = $(CrosView.IMPORT_DIV_ID).innerHTML; - $(CrosView.IMPORT_ONC_ID) - .addEventListener('change', handleFileChangeEvent_, false); - } - - /** - * Send file contents and passcode to C++ cros network library. - * - * @private - */ - function importONCFile_() { - clearParseStatus_(); - if (fileContent) { - g_browser.importONCFile(fileContent, passcode); - } else { - setParseStatus_('ONC file parse failed: cannot read file'); - } - clearFileInput_(); - } - - /** - * Set the passcode var, and trigger onc import. - * - * @param {string} value The passcode value. - * @private - */ - function setPasscode_(value) { - passcode = value; - if (passcode) { - importONCFile_(); - } - } - - /** - * Unhide the passcode prompt input field and give it focus. - * - * @private - */ - function promptForPasscode_() { - $(CrosView.PASSCODE_ID).hidden = false; - $(CrosView.PASSCODE_INPUT_ID).focus(); - $(CrosView.PASSCODE_INPUT_ID).select(); - } - - /** - * Set the fileContent var, and trigger onc import if the file appears to - * not be encrypted, or prompt for passcode if the file is encrypted. - * - * @private - * @param {string} text contents of selected file. - */ - function setFileContent_(result) { - fileContent = result; - // Parse the JSON to get at the top level "Type" property. - let jsonObject; - // Ignore any parse errors: they'll get handled in the C++ import code. - try { - jsonObject = JSON.parse(fileContent); - } catch (error) { - } - // Check if file is encrypted. - if (jsonObject && jsonObject.hasOwnProperty('Type') && - jsonObject.Type == 'EncryptedConfiguration') { - promptForPasscode_(); - } else { - importONCFile_(); - } - } - - /** - * Clear ONC file parse status. Clears and hides the parse status div. - * - * @private - */ - function clearParseStatus_(error) { - const parseStatus = $(CrosView.PARSE_STATUS_ID); - parseStatus.hidden = true; - parseStatus.textContent = ''; - } - - /** - * Set ONC file parse status. - * - * @private - */ - function setParseStatus_(error) { - const parseStatus = $(CrosView.PARSE_STATUS_ID); - parseStatus.hidden = false; - parseStatus.textContent = error ? 'ONC file parse failed: ' + error : - 'ONC file successfully parsed'; - reset_(); - } - - /** - * Set storing debug logs status. - * - * @private - */ - function setStoreDebugLogsStatus_(status) { - $(CrosView.STORE_DEBUG_LOGS_STATUS_ID).innerText = status; - } - - - /** - * Set storing combined debug logs status. - * - * @private - */ - function setStoreCombinedDebugLogsStatus_(status) { - $(CrosView.STORE_COMBINED_DEBUG_LOGS_STATUS_ID).innerText = status; - } - - /** - * Set storing combined debug logs status. - * - * @private - */ - function setStoreFeedbackSystemLogsStatus_(status) { - $(CrosView.STORE_FEEDBACK_SYSTEM_LOGS_STATUS_ID).innerText = status; - } - - /** - * Set status for current debug mode. - * - * @private - */ - function setNetworkDebugModeStatus_(status) { - $(CrosView.DEBUG_STATUS_ID).innerText = status; - } - - /** - * An event listener for the file selection field. - * - * @private - */ - function handleFileChangeEvent_(event) { - clearParseStatus_(); - const file = event.target.files[0]; - const reader = new FileReader(); - reader.onloadend = function(e) { - setFileContent_(reader.result); - }; - reader.readAsText(file); - } - - /** - * Add event listeners for the file selection, passcode input - * fields, for the button for debug logs storing and for buttons - * for debug mode selection. - * - * @private - */ - function addEventListeners_() { - $(CrosView.IMPORT_ONC_ID) - .addEventListener('change', handleFileChangeEvent_, false); - - $(CrosView.PASSCODE_INPUT_ID).addEventListener('change', function(event) { - setPasscode_(this.value); - }, false); - - $(CrosView.STORE_DEBUG_LOGS_ID).addEventListener('click', function(event) { - $(CrosView.STORE_DEBUG_LOGS_STATUS_ID).innerText = ''; - g_browser.storeDebugLogs(); - }, false); - $(CrosView.STORE_COMBINED_DEBUG_LOGS_ID) - .addEventListener('click', function(event) { - $(CrosView.STORE_COMBINED_DEBUG_LOGS_STATUS_ID).innerText = ''; - g_browser.storeCombinedDebugLogs(); - }, false); - $(CrosView.STORE_FEEDBACK_SYSTEM_LOGS_ID) - .addEventListener('click', function(event) { - $(CrosView.STORE_FEEDBACK_SYSTEM_LOGS_STATUS_ID).innerText = ''; - g_browser.storeFeedbackSystemLogs(); - }, false); - - $(CrosView.DEBUG_WIFI_ID).addEventListener('click', function(event) { - setNetworkDebugMode_('wifi'); - }, false); - $(CrosView.DEBUG_ETHERNET_ID).addEventListener('click', function(event) { - setNetworkDebugMode_('ethernet'); - }, false); - $(CrosView.DEBUG_CELLULAR_ID).addEventListener('click', function(event) { - setNetworkDebugMode_('cellular'); - }, false); - $(CrosView.DEBUG_NONE_ID).addEventListener('click', function(event) { - setNetworkDebugMode_('none'); - }, false); - } - - /** - * Reset fileContent and passcode vars. - * - * @private - */ - function reset_() { - fileContent = undefined; - passcode = ''; - $(CrosView.PASSCODE_ID).hidden = true; - } - - /** - * Enables or disables debug mode for a specified subsystem. - * - * @private - */ - function setNetworkDebugMode_(subsystem) { - $(CrosView.DEBUG_STATUS_ID).innerText = ''; - g_browser.setNetworkDebugMode(subsystem); - } - /** * @constructor * @extends {DivView} @@ -236,11 +17,6 @@ const CrosView = (function() { // Call superclass's constructor. DivView.call(this, CrosView.MAIN_BOX_ID); - - g_browser.addCrosONCFileParseObserver(this); - g_browser.addStoreDebugLogsObserver(this); - g_browser.addSetNetworkDebugModeObserver(this); - addEventListeners_(); } CrosView.TAB_ID = 'tab-handle-chromeos'; @@ -248,38 +24,12 @@ const CrosView = (function() { CrosView.TAB_HASH = '#chromeos'; CrosView.MAIN_BOX_ID = 'chromeos-view-tab-content'; - CrosView.IMPORT_DIV_ID = 'chromeos-view-import-div'; - CrosView.IMPORT_ONC_ID = 'chromeos-view-import-onc'; - CrosView.PASSCODE_ID = 'chromeos-view-password-div'; - CrosView.PASSCODE_INPUT_ID = 'chromeos-view-onc-password'; - CrosView.PARSE_STATUS_ID = 'chromeos-view-parse-status'; - CrosView.STORE_DEBUG_LOGS_ID = 'chromeos-view-store-debug-logs'; - CrosView.STORE_DEBUG_LOGS_STATUS_ID = 'chromeos-view-store-debug-logs-status'; - CrosView.STORE_COMBINED_DEBUG_LOGS_ID = - 'chromeos-view-store-combined-debug-logs'; - CrosView.STORE_COMBINED_DEBUG_LOGS_STATUS_ID = - 'chromeos-view-store-combined-debug-logs-status'; - CrosView.STORE_FEEDBACK_SYSTEM_LOGS_ID = - 'chromeos-view-store-feedback-system-logs'; - CrosView.STORE_FEEDBACK_SYSTEM_LOGS_STATUS_ID = - 'chromeos-view-store-feedback-system-logs-status'; - CrosView.DEBUG_WIFI_ID = 'chromeos-view-network-debugging-wifi'; - CrosView.DEBUG_ETHERNET_ID = 'chromeos-view-network-debugging-ethernet'; - CrosView.DEBUG_CELLULAR_ID = 'chromeos-view-network-debugging-cellular'; - CrosView.DEBUG_NONE_ID = 'chromeos-view-network-debugging-none'; - CrosView.DEBUG_STATUS_ID = 'chromeos-view-network-debugging-status'; cr.addSingletonGetter(CrosView); CrosView.prototype = { // Inherit from DivView. __proto__: DivView.prototype, - - onONCFileParse: setParseStatus_, - onStoreDebugLogs: setStoreDebugLogsStatus_, - onStoreCombinedDebugLogs: setStoreCombinedDebugLogsStatus_, - onStoreFeedbackSystemLogs: setStoreFeedbackSystemLogsStatus_, - onSetNetworkDebugMode: setNetworkDebugModeStatus_, }; return CrosView; diff --git a/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.html b/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.html index aaac84b199c..746c4c63572 100644 --- a/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.html +++ b/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.html @@ -45,6 +45,13 @@ Transparency information. See <a href="https://tools.ietf.org/html/draft-ietf-httpbis-expect-ct" target=_blank>https://tools.ietf.org/html/draft-ietf-httpbis-expect-ct</a>.</div> + <p>To protect against cross-site tracking, Expect-CT data will soon be keyed + on the site of the main frame and innermost frame when an Expect-CT + header is encountered. When that behavior is enabled, both adding and + querying an Expect-CT domain use the eTLD+1 of the provided domain as + the site for both frames. Deleting policies affects information stored + for that domain in the context of all sites, however.</p> + <h4>Add Expect-CT domain</h4> <p>Input a domain name to add it to the Expect-CT set. Leave Enforce unchecked diff --git a/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.js b/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.js index 5e5bcd4ad09..67126e523a3 100644 --- a/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.js +++ b/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.js @@ -152,7 +152,7 @@ const DomainSecurityPolicyView = (function() { onHSTSQueryResult(result) { if (result.error != undefined) { - this.queryStsOutputDiv_.innerHTML = ''; + this.queryStsOutputDiv_.innerHTML = trustedTypes.emptyHTML; const s = addNode(this.queryStsOutputDiv_, 'span'); s.textContent = result.error; s.style.color = '#e00'; @@ -161,15 +161,21 @@ const DomainSecurityPolicyView = (function() { } if (result.result == false) { - this.queryStsOutputDiv_.innerHTML = '<b>Not found</b>'; + this.queryStsOutputDiv_.innerHTML = trustedTypes.emptyHTML; + const notFound = document.createElement('b'); + notFound.textContent = 'Not found'; + this.queryStsOutputDiv_.appendChild(notFound); yellowFade(this.queryStsOutputDiv_); return; } - this.queryStsOutputDiv_.innerHTML = ''; + this.queryStsOutputDiv_.innerHTML = trustedTypes.emptyHTML; const s = addNode(this.queryStsOutputDiv_, 'span'); - s.innerHTML = '<b>Found:</b><br/>'; + const found = document.createElement('b'); + found.textContent = 'Found:'; + s.appendChild(found); + s.appendChild(document.createElement('br')); const keys = [ 'static_sts_domain', @@ -244,7 +250,7 @@ const DomainSecurityPolicyView = (function() { onExpectCTQueryResult(result) { if (result.error != undefined) { - this.queryExpectCTOutputDiv_.innerHTML = ''; + this.queryExpectCTOutputDiv_.innerHTML = trustedTypes.emptyHTML; const s = addNode(this.queryExpectCTOutputDiv_, 'span'); s.textContent = result.error; s.style.color = '#e00'; @@ -253,15 +259,21 @@ const DomainSecurityPolicyView = (function() { } if (result.result == false) { - this.queryExpectCTOutputDiv_.innerHTML = '<b>Not found</b>'; + this.queryExpectCTOutputDiv_.innerHTML = trustedTypes.emptyHTML; + const notFound = document.createElement('b'); + notFound.textContent = 'Not found'; + this.queryExpectCTOutputDiv_.appendChild(notFound); yellowFade(this.queryExpectCTOutputDiv_); return; } - this.queryExpectCTOutputDiv_.innerHTML = ''; + this.queryExpectCTOutputDiv_.innerHTML = trustedTypes.emptyHTML; const s = addNode(this.queryExpectCTOutputDiv_, 'span'); - s.innerHTML = '<b>Found:</b><br/>'; + const found = document.createElement('b'); + found.textContent = 'Found:'; + s.appendChild(found); + s.appendChild(document.createElement('br')); const keys = [ 'dynamic_expect_ct_domain', diff --git a/chromium/chrome/browser/resources/net_internals/events_view.html b/chromium/chrome/browser/resources/net_internals/events_view.html index 2b00d73bfa2..950e3ca8236 100644 --- a/chromium/chrome/browser/resources/net_internals/events_view.html +++ b/chromium/chrome/browser/resources/net_internals/events_view.html @@ -1,6 +1,6 @@ <!-- ================= Events view =================== --> <div id=events-view-tab-content class=content-box> The net-internals events viewer and related functionality has been removed. - Please use <a href="chrome://net-export">chrome://net-export</a> to save netlogs and the external <a href="https://chromium.googlesource.com/catapult/+/master/netlog_viewer/">catapult netlog_viewer</a> to view them. + Please use <a href="chrome://net-export">chrome://net-export</a> to save netlogs and the external <a href="https://netlog-viewer.appspot.com/">netlog_viewer</a> to view them. </div> diff --git a/chromium/chrome/browser/resources/net_internals/index.html b/chromium/chrome/browser/resources/net_internals/index.html index 56f50557873..cf44da3960d 100644 --- a/chromium/chrome/browser/resources/net_internals/index.html +++ b/chromium/chrome/browser/resources/net_internals/index.html @@ -30,6 +30,5 @@ found in the LICENSE file. <include src="chromeos_view.html"> </div> - <script src="chrome://resources/js/jstemplate_compiled.js"></script> </body> </html> diff --git a/chromium/chrome/browser/resources/net_internals/net_internals_resources.grd b/chromium/chrome/browser/resources/net_internals/net_internals_resources.grd index dddecdbee29..5dc7b0e4a8f 100644 --- a/chromium/chrome/browser/resources/net_internals/net_internals_resources.grd +++ b/chromium/chrome/browser/resources/net_internals/net_internals_resources.grd @@ -10,8 +10,8 @@ </outputs> <release seq="1"> <includes> - <include name="IDR_NET_INTERNALS_INDEX_HTML" file="index.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" /> - <include name="IDR_NET_INTERNALS_INDEX_JS" file="index.js" flattenhtml="true" compress="gzip" type="BINDATA" /> + <include name="IDR_NET_INTERNALS_INDEX_HTML" file="index.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> + <include name="IDR_NET_INTERNALS_INDEX_JS" file="index.js" flattenhtml="true" type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/new_tab_page/BUILD.gn b/chromium/chrome/browser/resources/new_tab_page/BUILD.gn index c8a9b38a86f..ded22388136 100644 --- a/chromium/chrome/browser/resources/new_tab_page/BUILD.gn +++ b/chromium/chrome/browser/resources/new_tab_page/BUILD.gn @@ -6,6 +6,7 @@ import("//chrome/browser/resources/optimize_webui.gni") import("//third_party/closure_compiler/compile_js.gni") import("//tools/grit/grit_rule.gni") import("//tools/polymer/html_to_js.gni") +import("//ui/webui/webui_features.gni") js_type_check("closure_compile") { is_polymer3 = true @@ -16,6 +17,7 @@ js_type_check("closure_compile") { ":doodle_share_dialog", ":fakebox", ":grid", + ":iframe", ":logo", ":realbox", ":realbox_button", @@ -23,7 +25,6 @@ js_type_check("closure_compile") { ":realbox_icon", ":realbox_match", ":theme_icon", - ":untrusted_iframe", ":utils", ":voice_search_overlay", ] @@ -122,13 +123,15 @@ js_library("grid") { js_library("voice_search_overlay") { deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_button:cr_button.m", + "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m", ] } js_library("utils") { } -js_library("untrusted_iframe") { +js_library("iframe") { deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] @@ -226,7 +229,7 @@ html_to_js("web_components") { "realbox_match.js", "realbox.js", "theme_icon.js", - "untrusted_iframe.js", + "iframe.js", "voice_search_overlay.js", ] } @@ -259,6 +262,12 @@ if (optimize_webui) { pak_file = "new_tab_page_resources.pak" out_folder = "unpak" deps = [ ":unoptimized_resources" ] + + excludes = [ + "../../ui/webui/new_tab_page/new_tab_page.mojom-lite.js", + "../../../common/search/omnibox.mojom-lite.js", + "../../../../skia/public/mojom/skcolor.mojom-lite.js", + ] } optimize_webui("optimized_js") { @@ -277,10 +286,10 @@ if (optimize_webui) { "chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js", "chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js", "chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js", + "chrome://resources/mojo/skia/public/mojom/skcolor.mojom-lite.js", "chrome://resources/mojo/url/mojom/url.mojom-lite.js", "new_tab_page.mojom-lite.js", "omnibox.mojom-lite.js", - "skcolor.mojom-lite.js", ] } } diff --git a/chromium/chrome/browser/resources/new_tab_page/app.html b/chromium/chrome/browser/resources/new_tab_page/app.html index 381379df828..5758e8a6d49 100644 --- a/chromium/chrome/browser/resources/new_tab_page/app.html +++ b/chromium/chrome/browser/resources/new_tab_page/app.html @@ -18,12 +18,24 @@ } #oneGoogleBar { - clip-path: url(#oneGoogleBarClipPath); height: 100%; position: absolute; top: 0; width: 100%; - z-index: 1000; + } + + #oneGoogleBarOverlayBackdrop { + background: rgba(0, 0, 0, .6); + display: none; + height: 100%; + position: fixed; + top: 0; + width: 100%; + z-index: 999; + } + + #oneGoogleBarOverlayBackdrop[show] { + display: block; } #content { @@ -223,20 +235,19 @@ --ntp-theme-shortcut-background-color: [[rgbaOrInherit_(theme_.shortcutBackgroundColor)]]; --ntp-logo-color: [[rgbaOrInherit_(logoColor_)]];"> - <dom-if if="[[showIframedOneGoogleBar_]]"> - <template> - <ntp-untrusted-iframe id="oneGoogleBar" path="[[oneGoogleBarIframePath_]]" - hidden$="[[!oneGoogleBarLoaded_]]"> - </ntp-untrusted-iframe> - </template> - </dom-if> + <template is="dom-if" if="[[showIframedOneGoogleBar_]]"> + <ntp-iframe id="oneGoogleBar" src="[[oneGoogleBarIframePath_]]" + hidden$="[[!oneGoogleBarLoaded_]]"> + </ntp-iframe> + </template> <ntp-logo id="logo" doodle-allowed$="[[doodleAllowed_]]" - single-colored$="[[singleColoredLogo_]]"> + single-colored$="[[singleColoredLogo_]]" dark="[[theme_.isDark]]" + background-color="[[backgroundColor_]]"> </ntp-logo> - <ntp-fakebox id="fakebox" on-open-voice-search="onVoiceSearchClick_" + <ntp-fakebox id="fakebox" on-open-voice-search="onOpenVoiceSearch_" hidden$="[[realboxEnabled_]]"> </ntp-fakebox> - <ntp-realbox id="realbox" on-open-voice-search="onVoiceSearchClick_" + <ntp-realbox id="realbox" on-open-voice-search="onOpenVoiceSearch_" theme="[[theme_.searchBox]]" shown$="[[realboxShown_]]" hidden$="[[!realboxEnabled_]]"> </ntp-realbox> @@ -246,8 +257,9 @@ </ntp-most-visited> <dom-if if="[[lazyRender_]]"> <template> - <ntp-untrusted-iframe id="promo" path="promo" hidden$="[[!promoLoaded_]]"> - </ntp-untrusted-iframe> + <ntp-iframe id="promo" hidden$="[[!promoLoaded_]]" + src="chrome-untrusted://new-tab-page/promo"> + </ntp-iframe> <a id="backgroundImageAttribution" href="[[backgroundImageAttributionUrl_]]" hidden="[[!backgroundImageAttribution1_]]"> @@ -297,10 +309,9 @@ </ntp-customize-dialog> </template> </dom-if> +<div id="oneGoogleBarOverlayBackdrop"></div> <svg> <defs> - <clipPath id="oneGoogleBarClipPath"> - <rect x="0" y="0" width="100vw" height="56"></rect> - </clipPath> + <clipPath id="oneGoogleBarClipPath"></clipPath> </defs> </svg> diff --git a/chromium/chrome/browser/resources/new_tab_page/app.js b/chromium/chrome/browser/resources/new_tab_page/app.js index 74dbea61053..121633a3d00 100644 --- a/chromium/chrome/browser/resources/new_tab_page/app.js +++ b/chromium/chrome/browser/resources/new_tab_page/app.js @@ -6,7 +6,7 @@ import './strings.m.js'; import './most_visited.js'; import './customize_dialog.js'; import './voice_search_overlay.js'; -import './untrusted_iframe.js'; +import './iframe.js'; import './fakebox.js'; import './realbox.js'; import './logo.js'; @@ -50,6 +50,13 @@ class AppElement extends PolymerElement { }, /** @private */ + oneGoogleBarModalOverlaysEnabled_: { + type: Boolean, + value: () => + loadTimeData.getBoolean('oneGoogleBarModalOverlaysEnabled'), + }, + + /** @private */ oneGoogleBarIframePath_: { type: String, value: () => { @@ -57,12 +64,13 @@ class AppElement extends PolymerElement { params.set( 'paramsencoded', btoa(window.location.search.replace(/^[?]/, '&'))); - return `one-google-bar?${params}`; + return `chrome-untrusted://new-tab-page/one-google-bar?${params}`; }, }, /** @private */ oneGoogleBarLoaded_: { + observer: 'oneGoogleBarLoadedChange_', type: Boolean, value: false, }, @@ -143,6 +151,12 @@ class AppElement extends PolymerElement { type: Boolean, }, + /** @private {skia.mojom.SkColor} */ + backgroundColor_: { + computed: 'computeBackgroundColor_(showBackgroundImage_, theme_)', + type: Object, + }, + /** @private */ logoColor_: { type: String, @@ -181,6 +195,8 @@ class AppElement extends PolymerElement { super(); /** @private {!newTabPage.mojom.PageCallbackRouter} */ this.callbackRouter_ = BrowserProxy.getInstance().callbackRouter; + /** @private {newTabPage.mojom.PageHandlerRemote} */ + this.pageHandler_ = BrowserProxy.getInstance().handler; /** @private {!BackgroundManager} */ this.backgroundManager_ = BackgroundManager.getInstance(); /** @private {?number} */ @@ -223,6 +239,7 @@ class AppElement extends PolymerElement { } } }); + this.eventTracker_.add(window, 'keydown', e => this.onWindowKeydown_(e)); if (this.shouldPrintPerformance_) { // It is possible that the background image has already loaded by now. // If it has, we request it to re-send the load time so that we can @@ -292,9 +309,8 @@ class AppElement extends PolymerElement { return; } - const {parts} = - await BrowserProxy.getInstance().handler.getOneGoogleBarParts( - window.location.search.replace(/^[?]/, '&')); + const {parts} = await this.pageHandler_.getOneGoogleBarParts( + window.location.search.replace(/^[?]/, '&')); if (!parts) { return; } @@ -327,8 +343,7 @@ class AppElement extends PolymerElement { endOfBodyScript.appendChild(document.createTextNode(parts.endOfBodyScript)); document.body.appendChild(endOfBodyScript); - BrowserProxy.getInstance().handler.onOneGoogleBarRendered( - BrowserProxy.getInstance().now()); + this.pageHandler_.onOneGoogleBarRendered(BrowserProxy.getInstance().now()); } /** @private */ @@ -428,8 +443,10 @@ class AppElement extends PolymerElement { } /** @private */ - onVoiceSearchClick_() { + onOpenVoiceSearch_() { this.showVoiceSearchOverlay_ = true; + this.pageHandler_.onVoiceSearchAction( + newTabPage.mojom.VoiceSearchAction.ACTIVATE_SEARCH_BOX); } /** @private */ @@ -448,6 +465,24 @@ class AppElement extends PolymerElement { } /** + * Handles <CTRL> + <SHIFT> + <.> (also <CMD> + <SHIFT> + <.> on mac) to open + * voice search. + * @param {KeyboardEvent} e + * @private + */ + onWindowKeydown_(e) { + let ctrlKeyPressed = e.ctrlKey; + // <if expr="is_macosx"> + ctrlKeyPressed = ctrlKeyPressed || e.metaKey; + // </if> + if (ctrlKeyPressed && e.code === 'Period' && e.shiftKey) { + this.showVoiceSearchOverlay_ = true; + this.pageHandler_.onVoiceSearchAction( + newTabPage.mojom.VoiceSearchAction.ACTIVATE_KEYBOARD); + } + } + + /** * @param {skia.mojom.SkColor} skColor * @return {string} * @private @@ -547,7 +582,8 @@ class AppElement extends PolymerElement { * @private */ computeDoodleAllowed_() { - return !this.showBackgroundImage_ && this.theme_ && + return loadTimeData.getBoolean('themeModeDoodlesEnabled') || + !this.showBackgroundImage_ && this.theme_ && this.theme_.type === newTabPage.mojom.ThemeType.DEFAULT && !this.theme_.isDark; } @@ -556,6 +592,17 @@ class AppElement extends PolymerElement { * @return {skia.mojom.SkColor} * @private */ + computeBackgroundColor_() { + if (this.showBackgroundImage_) { + return null; + } + return this.theme_ && this.theme_.backgroundColor; + } + + /** + * @return {skia.mojom.SkColor} + * @private + */ computeLogoColor_() { switch (this.backgroundSelection_.type) { case BackgroundSelectionType.IMAGE: @@ -589,31 +636,47 @@ class AppElement extends PolymerElement { /** * Handles messages from the OneGoogleBar iframe. The messages that are * handled include show bar on load and overlay updates. + * * 'overlaysUpdated' message includes the updated array of overlay rects that * are shown. + * + * When modal overlays are enabled, activate/deactivate controls if the + * OneGoogleBar is layered on top of #content with a backdrop. This would + * happen when OneGoogleBar has an overlay open. * @param {!Object} data * @private */ handleOneGoogleBarMessage_(data) { if (data.messageType === 'loaded') { + if (!this.oneGoogleBarModalOverlaysEnabled_) { + const oneGoogleBar = $$(this, '#oneGoogleBar'); + oneGoogleBar.style.clipPath = 'url(#oneGoogleBarClipPath)'; + oneGoogleBar.style.zIndex = '1000'; + } this.oneGoogleBarLoaded_ = true; - BrowserProxy.getInstance().handler.onOneGoogleBarRendered( + this.pageHandler_.onOneGoogleBarRendered( BrowserProxy.getInstance().now()); } else if (data.messageType === 'overlaysUpdated') { - this.$.oneGoogleBarClipPath.querySelectorAll('rect:not(:first-child)') - .forEach(el => { - el.remove(); - }); + this.$.oneGoogleBarClipPath.querySelectorAll('rect').forEach(el => { + el.remove(); + }); const overlayRects = /** @type {!Array<!DOMRect>} */ (data.data); overlayRects.forEach(({x, y, width, height}) => { const rectElement = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); - rectElement.setAttribute('x', x); - rectElement.setAttribute('y', y); - rectElement.setAttribute('width', width); - rectElement.setAttribute('height', height); + // Add 8px around every rect to ensure shadows are not cutoff. + rectElement.setAttribute('x', x - 8); + rectElement.setAttribute('y', y - 8); + rectElement.setAttribute('width', width + 16); + rectElement.setAttribute('height', height + 16); this.$.oneGoogleBarClipPath.appendChild(rectElement); }); + } else if (data.messageType === 'activate') { + this.$.oneGoogleBarOverlayBackdrop.toggleAttribute('show', true); + $$(this, '#oneGoogleBar').style.zIndex = '1000'; + } else if (data.messageType === 'deactivate') { + this.$.oneGoogleBarOverlayBackdrop.toggleAttribute('show', false); + $$(this, '#oneGoogleBar').style.zIndex = '0'; } } @@ -634,14 +697,64 @@ class AppElement extends PolymerElement { }; this.eventTracker_.add(window, 'resize', onResize); onResize(); - BrowserProxy.getInstance().handler.onPromoRendered( - BrowserProxy.getInstance().now()); + this.pageHandler_.onPromoRendered(BrowserProxy.getInstance().now()); } else if (data.messageType === 'link-clicked') { - BrowserProxy.getInstance().handler.onPromoLinkClicked( - BrowserProxy.getInstance().now()); + this.pageHandler_.onPromoLinkClicked(); + } + } + + /** @private */ + oneGoogleBarLoadedChange_() { + if (this.oneGoogleBarLoaded_ && this.iframeOneGoogleBarEnabled_ && + this.oneGoogleBarModalOverlaysEnabled_) { + this.setupShortcutDragDropOneGoogleBarWorkaround_(); } } + /** + * During a shortcut drag, an iframe behind ntp-most-visited will prevent + * 'dragover' events from firing. To workaround this, 'pointer-events: none' + * can be set on the iframe. When doing this after the 'dragstart' event is + * fired is too late. We can instead set 'pointer-events: none' when the + * pointer enters ntp-most-visited. + * + * 'pointerenter' and pointerleave' events fire during drag. The iframe + * 'pointer-events' needs to be reset to the original value when 'dragend' + * fires if the pointer has left ntp-most-visited. + * @private + */ + setupShortcutDragDropOneGoogleBarWorkaround_() { + const iframe = $$(this, '#oneGoogleBar'); + let resetAtDragEnd = false; + let dragging = false; + let originalPointerEvents; + this.eventTracker_.add(this.$.mostVisited, 'pointerenter', () => { + if (dragging) { + resetAtDragEnd = false; + return; + } + originalPointerEvents = getComputedStyle(iframe).pointerEvents; + iframe.style.pointerEvents = 'none'; + }); + this.eventTracker_.add(this.$.mostVisited, 'pointerleave', () => { + if (dragging) { + resetAtDragEnd = true; + return; + } + iframe.style.pointerEvents = originalPointerEvents; + }); + this.eventTracker_.add(this.$.mostVisited, 'dragstart', () => { + dragging = true; + }); + this.eventTracker_.add(this.$.mostVisited, 'dragend', () => { + dragging = false; + if (resetAtDragEnd) { + resetAtDragEnd = false; + iframe.style.pointerEvents = originalPointerEvents; + } + }); + } + /** @private */ printPerformanceDatum_(name, time, auxTime = 0) { if (!this.shouldPrintPerformance_) { diff --git a/chromium/chrome/browser/resources/new_tab_page/browser_proxy.js b/chromium/chrome/browser/resources/new_tab_page/browser_proxy.js index c91deaf6a0a..ea8db362e8a 100644 --- a/chromium/chrome/browser/resources/new_tab_page/browser_proxy.js +++ b/chromium/chrome/browser/resources/new_tab_page/browser_proxy.js @@ -7,10 +7,10 @@ import 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js' import 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js'; import 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js'; import 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js'; +import 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-lite.js'; import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js'; import './omnibox.mojom-lite.js'; -import './skcolor.mojom-lite.js'; import './new_tab_page.mojom-lite.js'; import {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; @@ -59,11 +59,11 @@ export class BrowserProxy { } /** - * @param {string} path + * @param {string} src * @return {string} */ - createUntrustedIframeSrc(path) { - return `chrome-untrusted://new-tab-page/${path}`; + createIframeSrc(src) { + return src; } /** diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.html b/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.html index bd734769a8e..f7e131a8742 100644 --- a/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.html +++ b/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.html @@ -1,7 +1,6 @@ <style include="cr-hidden-style"> :host { display: flex; - height: -webkit-fill-available; } #container { @@ -17,7 +16,7 @@ outline-width: 0; } - ntp-untrusted-iframe { + ntp-iframe { pointer-events: none; } @@ -197,9 +196,9 @@ <template> <div class="tile" tabindex="0" title="[[item.label]]" role="button" on-click="onCollectionClick_"> - <ntp-untrusted-iframe class="image" - path="background_image?[[item.previewImageUrl.url]]"> - </ntp-untrusted-iframe> + <ntp-iframe class="image" + src="chrome-untrusted://new-tab-page/background_image?[[item.previewImageUrl.url]]"> + </ntp-iframe> <div class="label">[[item.label]]</div> </div> </template> @@ -213,9 +212,9 @@ [[getImageSelectedClass_(index, theme, backgroundSelection)]]" tabindex="0" title="[[item.attribution1]]" role="button" on-click="onImageClick_"> - <ntp-untrusted-iframe class="image" - path="background_image?[[item.previewImageUrl.url]]"> - </ntp-untrusted-iframe> + <ntp-iframe class="image" + src="chrome-untrusted://new-tab-page/background_image?[[item.previewImageUrl.url]]"> + </ntp-iframe> <div class="selected-circle"></div> <div class="selected-check"></div> </div> diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.js b/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.js index 75ccde66924..4f99d35e938 100644 --- a/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.js +++ b/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.js @@ -5,7 +5,7 @@ import 'chrome://resources/cr_elements/hidden_style_css.m.js'; import './grid.js'; import './mini_page.js'; -import './untrusted_iframe.js'; +import './iframe.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_dialog.html b/chromium/chrome/browser/resources/new_tab_page/customize_dialog.html index 481090004be..231ac1f603c 100644 --- a/chromium/chrome/browser/resources/new_tab_page/customize_dialog.html +++ b/chromium/chrome/browser/resources/new_tab_page/customize_dialog.html @@ -1,10 +1,16 @@ <style include="cr-hidden-style cr-icons"> - ::part(dialog) { + cr-dialog::part(dialog) { + height: 100%; + max-height: 520px; min-width: 800px; } - :host { - --border-width: 1px; + cr-dialog::part(wrapper) { + height: 100%; + } + + cr-dialog::part(body-container) { + flex-grow: 1; } div[slot=title] { @@ -36,7 +42,6 @@ #menuContainer, #pagesContainer { - max-height: 395px; overflow: hidden; } @@ -57,11 +62,7 @@ flex-grow: 1; } - #menu { - height: calc(100% - 2 * var(--border-width)); - overflow: auto; - } - + #menu, #pages { height: 100%; overflow: auto; @@ -70,11 +71,10 @@ #pages > iron-pages { /* Margin is for focus outline. */ margin: 2px; - min-height: 389px; } div[scroll-border] { - border-bottom: var(--border-width) solid transparent; + border-bottom: 1px solid transparent; } div[scroll-border][show-1], @@ -97,11 +97,14 @@ flex-shrink: 0; font-size: 14px; height: 32px; - margin-bottom: 16px; outline: none; width: 192px; } + .menu-item + .menu-item { + margin-top: 16px; + } + :host-context([dir=rtl]) .menu-item { border-radius: 16px 0 0 16px; } diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_themes.html b/chromium/chrome/browser/resources/new_tab_page/customize_themes.html index a0920f697b6..3fccbcba6b9 100644 --- a/chromium/chrome/browser/resources/new_tab_page/customize_themes.html +++ b/chromium/chrome/browser/resources/new_tab_page/customize_themes.html @@ -45,7 +45,6 @@ #themesContainer { --ntp-grid-gap: 20px; - padding: 3px; } #themesContainer > * { diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.html b/chromium/chrome/browser/resources/new_tab_page/iframe.html index 212f6d13acb..212f6d13acb 100644 --- a/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.html +++ b/chromium/chrome/browser/resources/new_tab_page/iframe.html diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.js b/chromium/chrome/browser/resources/new_tab_page/iframe.js index f40c0cd58cc..14afd7b04a7 100644 --- a/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.js +++ b/chromium/chrome/browser/resources/new_tab_page/iframe.js @@ -5,9 +5,14 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {BrowserProxy} from './browser_proxy.js'; -class UntrustedIframeElement extends PolymerElement { +/** + * @fileoverview Wrapper around <iframe> element that lets us mock out loading + * and postMessaging in tests. + */ + +class IframeElement extends PolymerElement { static get is() { - return 'ntp-untrusted-iframe'; + return 'ntp-iframe'; } static get template() { @@ -17,7 +22,7 @@ class UntrustedIframeElement extends PolymerElement { static get properties() { return { /** @type {string} */ - path: { + src: { reflectToAttribute: true, type: String, }, @@ -25,7 +30,7 @@ class UntrustedIframeElement extends PolymerElement { /** @private */ src_: { type: String, - computed: 'computeSrc_(path)', + computed: 'computeSrc_(src)', }, }; } @@ -35,14 +40,17 @@ class UntrustedIframeElement extends PolymerElement { * @param {*} message */ postMessage(message) { - this.$.iframe.contentWindow.postMessage( - message, 'chrome-untrusted://new-tab-page'); + BrowserProxy.getInstance().postMessage( + this.$.iframe, message, new URL(this.src).origin); } - /** @private */ + /** + * @return {string} + * @private + */ computeSrc_() { - return BrowserProxy.getInstance().createUntrustedIframeSrc(this.path); + return BrowserProxy.getInstance().createIframeSrc(this.src); } } -customElements.define(UntrustedIframeElement.is, UntrustedIframeElement); +customElements.define(IframeElement.is, IframeElement); diff --git a/chromium/chrome/browser/resources/new_tab_page/logo.html b/chromium/chrome/browser/resources/new_tab_page/logo.html index ce8504f079c..f9f1fe7e008 100644 --- a/chromium/chrome/browser/resources/new_tab_page/logo.html +++ b/chromium/chrome/browser/resources/new_tab_page/logo.html @@ -24,22 +24,38 @@ background-image: url(chrome://resources/images/google_logo.svg); } - #imageContainer { + #doodle { + display: flex; + flex-direction: column; + height: 100%; + justify-content: center; + } + + :host([doodle-boxed_]) #doodle { + justify-content: flex-end; + } + + #imageDoodle { cursor: pointer; - display: grid; - height: fit-content; outline: none; - position: relative; - width: fit-content; } - :host-context(.focus-outline-visible) #imageContainer:focus { + :host([doodle-boxed_]) #imageDoodle { + background-color: var(--ntp-logo-box-color); + border-radius: 20px; + margin-bottom: 30px; + padding: 16px 24px; + } + + :host-context(.focus-outline-visible) #imageDoodle:focus { box-shadow: 0 0 0 2px rgba(var(--google-blue-600-rgb), .4); } - #imageContainer > * { - grid-column-start: 1; - grid-row-start: 1; + #imageContainer { + display: flex; + height: fit-content; + position: relative; + width: fit-content; } #image { @@ -47,32 +63,46 @@ max-width: 100%; } + :host([doodle-boxed_]) #image { + max-height: 160px; + } + #animation { height: 100%; pointer-events: none; + position: absolute; width: 100%; } #shareButton { + background-color: var(--ntp-logo-share-button-background-color, none); border: none; - height: 26px; - min-width: 26px; + height: var(--ntp-logo-share-button-height, 0); + left: var(--ntp-logo-share-button-x, 0); + min-width: var(--ntp-logo-share-button-width, 0); opacity: 0.8; outline: initial; padding: 2px; position: absolute; - width: 26px; + top: var(--ntp-logo-share-button-y, 0); + width: var(--ntp-logo-share-button-width, 0); } #shareButton:hover { opacity: 1; } + #shareButton img { + height: 100%; + width: 100%; + } + #iframe { - height: var(--height); + border: none; + height: var(--height, --ntp-logo-height); transition-duration: var(--duration, 100ms); transition-property: height, width; - width: var(--width); + width: var(--width, 100%); } </style> <dom-if if="[[showLogo_]]" restamp> @@ -86,32 +116,28 @@ <dom-if if="[[showDoodle_]]" restamp> <template> <div id="doodle" title="[[doodle_.description]]"> - <div id="imageContainer" hidden="[[!doodle_.content.imageDoodle]]" - tabindex="1" on-click="onImageClick_" on-keydown="onImageKeydown_"> - <!-- The static image is always visible and the animated image is - stacked on top of the static image so that there is no flicker when - starting the animation. --> - <img id="image" src="[[imageUrl_]]" on-load="onImageLoad_"> - </img> - <ntp-untrusted-iframe id="animation" path="[[animationUrl_]]" - hidden="[[!showAnimation_]]"> - </ntp-untrusted-iframe> - <cr-button id="shareButton" title="$i18n{shareDoodle}" - on-click="onShareButtonClick_" - style="background-color: [[rgbaOrUnset_(doodle_.content.imageDoodle.shareButton.backgroundColor)]]; - left: [[doodle_.content.imageDoodle.shareButton.x]]px; - top: [[doodle_.content.imageDoodle.shareButton.y]]px;"> - <img id="shareButtonImage" - src="[[doodle_.content.imageDoodle.shareButton.iconUrl.url]]"> + <div id="imageDoodle" hidden="[[!imageDoodle_]]" + tabindex="0" on-click="onImageClick_" on-keydown="onImageKeydown_"> + <div id="imageContainer"> + <!-- The static image is always visible and the animated image is + stacked on top of the static image so that there is no flicker + when starting the animation. --> + <img id="image" src="[[imageUrl_]]" on-load="onImageLoad_"> </img> - </cr-button> + <ntp-iframe id="animation" src="[[animationUrl_]]" + hidden="[[!showAnimation_]]"> + </ntp-iframe> + <cr-button id="shareButton" title="$i18n{shareDoodle}" + on-click="onShareButtonClick_"> + <img id="shareButtonImage" + src="[[imageDoodle_.shareButton.iconUrl.url]]"> + </img> + </cr-button> + </div> </div> - <ntp-untrusted-iframe id="iframe" path="[[iframeUrl_]]" - hidden="[[!iframeUrl_]]" - style="--duration: [[valueOrUnset_(duration_)]]; - --height: [[valueOrUnset_(height_)]]; - --width: [[valueOrUnset_(width_)]];"> - </ntp-untrusted-iframe> + <template is="dom-if" if="[[iframeUrl_]]" restamp> + <ntp-iframe id="iframe" src="[[iframeUrl_]]"></ntp-iframe> + </template> </div> </template> </dom-if> diff --git a/chromium/chrome/browser/resources/new_tab_page/logo.js b/chromium/chrome/browser/resources/new_tab_page/logo.js index 41af57ef294..78987000940 100644 --- a/chromium/chrome/browser/resources/new_tab_page/logo.js +++ b/chromium/chrome/browser/resources/new_tab_page/logo.js @@ -4,14 +4,19 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/hidden_style_css.m.js'; -import './untrusted_iframe.js'; +import './iframe.js'; import './doodle_share_dialog.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + import {BrowserProxy} from './browser_proxy.js'; -import {skColorToRgba} from './utils.js'; +import {$$, skColorToRgba} from './utils.js'; + +/** @type {number} */ +const SHARE_BUTTON_SIZE_PX = 26; // Shows the Google logo or a doodle if available. class LogoElement extends PolymerElement { @@ -45,15 +50,38 @@ class LogoElement extends PolymerElement { value: false, }, + /** + * If true displays the dark mode doodle if possible. + * @type {boolean} + */ + dark: { + observer: 'onDarkChange_', + type: Boolean, + }, + + /** + * The NTP's background color. If null or undefined the NTP does not have + * a single background color, e.g. when a background image is set. + * @type {skia.mojom.SkColor} + */ + backgroundColor: Object, + /** @private */ loaded_: Boolean, /** @private {newTabPage.mojom.Doodle} */ doodle_: Object, + /** @private {newTabPage.mojom.ImageDoodle} */ + imageDoodle_: { + observer: 'onImageDoodleChange_', + computed: 'computeImageDoodle_(dark, doodle_)', + type: Object, + }, + /** @private */ canShowDoodle_: { - computed: 'computeCanShowDoodle_(doodle_)', + computed: 'computeCanShowDoodle_(doodle_, imageDoodle_)', type: Boolean, }, @@ -70,8 +98,15 @@ class LogoElement extends PolymerElement { }, /** @private */ + doodleBoxed_: { + reflectToAttribute: true, + type: Boolean, + computed: 'computeDoodleBoxed_(backgroundColor, imageDoodle_)', + }, + + /** @private */ imageUrl_: { - computed: 'computeImageUrl_(doodle_)', + computed: 'computeImageUrl_(imageDoodle_)', type: String, }, @@ -83,7 +118,7 @@ class LogoElement extends PolymerElement { /** @private */ animationUrl_: { - computed: 'computeAnimationUrl_(doodle_)', + computed: 'computeAnimationUrl_(imageDoodle_)', type: String, }, @@ -95,20 +130,20 @@ class LogoElement extends PolymerElement { /** @private */ duration_: { + observer: 'onDurationHeightWidthChange_', type: String, - value: null, }, /** @private */ height_: { + observer: 'onDurationHeightWidthChange_', type: String, - value: null, }, /** @private */ width_: { + observer: 'onDurationHeightWidthChange_', type: String, - value: null, }, /** @private */ @@ -132,24 +167,27 @@ class LogoElement extends PolymerElement { } }); /** @private {?string} */ - this.imageClickParams_; + this.imageClickParams_ = null; /** @private {url.mojom.Url} */ - this.interactionLogUrl_; + this.interactionLogUrl_ = null; /** @private {?string} */ - this.shareId_; + this.shareId_ = null; } /** @override */ connectedCallback() { super.connectedCallback(); this.eventTracker_.add(window, 'message', ({data}) => { - if (data['cmd'] !== 'resizeDoodle') { - return; + if (data['cmd'] === 'resizeDoodle') { + this.duration_ = assert(data.duration); + this.height_ = assert(data.height); + this.width_ = assert(data.width); + } else if (data['cmd'] === 'sendMode') { + this.sendMode_(); } - this.duration_ = assert(data.duration); - this.height_ = assert(data.height); - this.width_ = assert(data.width); }); + // Make sure the doodle gets the mode in case it has already requested it. + this.sendMode_(); } /** @override */ @@ -164,15 +202,63 @@ class LogoElement extends PolymerElement { performance.measure('logo-creation', 'logo-creation-start'); } + /** @private */ + onImageDoodleChange_() { + if (this.imageDoodle_) { + const shareButton = this.imageDoodle_.shareButton; + const height = this.imageDoodle_.height; + const width = this.imageDoodle_.width; + this.updateStyles({ + '--ntp-logo-share-button-background-color': + skColorToRgba(shareButton.backgroundColor), + '--ntp-logo-share-button-height': + `${SHARE_BUTTON_SIZE_PX / height * 100}%`, + '--ntp-logo-share-button-width': + `${SHARE_BUTTON_SIZE_PX / width * 100}%`, + '--ntp-logo-share-button-x': `${shareButton.x / width * 100}%`, + '--ntp-logo-share-button-y': `${shareButton.y / height * 100}%`, + '--ntp-logo-box-color': + skColorToRgba(this.imageDoodle_.backgroundColor), + }); + } else { + this.updateStyles({ + '--ntp-logo-share-button-background-color': null, + '--ntp-logo-share-button-height': null, + '--ntp-logo-share-button-width': null, + '--ntp-logo-share-button-x': null, + '--ntp-logo-share-button-y': null, + '--ntp-logo-box-color': null, + }); + } + // Stop the animation (if it is running) and reset logging params since + // mode change constitutes a new doodle session. + this.showAnimation_ = false; + this.imageClickParams_ = null; + this.interactionLogUrl_ = null; + this.shareId_ = null; + } + + /** + * @return {newTabPage.mojom.ImageDoodle} + * @private + */ + computeImageDoodle_() { + return this.doodle_ && this.doodle_.content.imageDoodle && + (this.dark ? this.doodle_.content.imageDoodle.dark : + this.doodle_.content.imageDoodle.light) || + null; + } + /** * @return {boolean} * @private */ computeCanShowDoodle_() { - return !!this.doodle_ && + return !!this.imageDoodle_ || /* We hide interactive doodles when offline. Otherwise, the iframe would show an ugly error page. */ - (!this.doodle_.content.interactiveDoodle || window.navigator.onLine); + !!this.doodle_ && !!this.doodle_.content.interactiveDoodle && + window.navigator.onLine; } /** @@ -192,6 +278,16 @@ class LogoElement extends PolymerElement { } /** + * @return {boolean} + * @private + */ + computeDoodleBoxed_() { + return !this.backgroundColor || + !!this.imageDoodle_ && + this.imageDoodle_.backgroundColor.value !== this.backgroundColor.value; + } + + /** * Called when a simple or animated doodle was clicked. Starts animation if * clicking preview image of animated doodle. Otherwise, opens * doodle-associated URL in new tab/window. @@ -211,7 +307,7 @@ class LogoElement extends PolymerElement { this.logImageRendered_( newTabPage.mojom.DoodleImageType.ANIMATION, /** @type {!url.mojom.Url} */ - (this.doodle_.content.imageDoodle.animationImpressionLogUrl)); + (this.imageDoodle_.animationImpressionLogUrl)); return; } @@ -233,7 +329,7 @@ class LogoElement extends PolymerElement { this.logImageRendered_( this.isCtaImageShown_() ? newTabPage.mojom.DoodleImageType.CTA : newTabPage.mojom.DoodleImageType.STATIC, - this.doodle_.content.imageDoodle.imageImpressionLogUrl); + this.imageDoodle_.imageImpressionLogUrl); } /** @@ -278,58 +374,62 @@ class LogoElement extends PolymerElement { * @private */ isCtaImageShown_() { - return !this.showAnimation_ && !!this.doodle_ && - !!this.doodle_.content.imageDoodle.animationUrl; + return !this.showAnimation_ && !!this.imageDoodle_.animationUrl; } /** - * @return {string} + * Sends a postMessage to the interactive doodle whether the current theme is + * dark or light. Won't do anything if we don't have an interactive doodle or + * we haven't been told yet whether the current theme is dark or light. * @private */ - computeImageUrl_() { - return (this.doodle_ && this.doodle_.content.imageDoodle && - this.doodle_.content.imageDoodle.imageUrl) ? - this.doodle_.content.imageDoodle.imageUrl.url : - ''; + sendMode_() { + const iframe = $$(this, '#iframe'); + if (!loadTimeData.getBoolean('themeModeDoodlesEnabled') || + this.dark === undefined || !iframe) { + return; + } + iframe.postMessage({cmd: 'changeMode', dark: this.dark}); } - /** - * @return {string} - * @private - */ - computeAnimationUrl_() { - return (this.doodle_ && this.doodle_.content.imageDoodle && - this.doodle_.content.imageDoodle.animationUrl) ? - `image?${this.doodle_.content.imageDoodle.animationUrl.url}` : - ''; + /** @private */ + onDarkChange_() { + this.sendMode_(); } /** * @return {string} * @private */ - computeIframeUrl_() { - return (this.doodle_ && this.doodle_.content.interactiveDoodle) ? - `iframe?${this.doodle_.content.interactiveDoodle.url.url}` : - ''; + computeImageUrl_() { + return this.imageDoodle_ ? this.imageDoodle_.imageUrl.url : ''; } /** - * @param {string} value * @return {string} * @private */ - valueOrUnset_(value) { - return value || 'unset'; + computeAnimationUrl_() { + return this.imageDoodle_ && this.imageDoodle_.animationUrl ? + `chrome-untrusted://new-tab-page/image?${ + this.imageDoodle_.animationUrl.url}` : + ''; } /** - * @param {skia.mojom.SkColor} skColor * @return {string} * @private */ - rgbaOrUnset_(skColor) { - return skColor ? skColorToRgba(skColor) : 'unset'; + computeIframeUrl_() { + if (this.doodle_ && this.doodle_.content.interactiveDoodle) { + const url = new URL(this.doodle_.content.interactiveDoodle.url.url); + if (loadTimeData.getBoolean('themeModeDoodlesEnabled')) { + url.searchParams.append('theme_messages', '0'); + } + return url.href; + } else { + return ''; + } } /** @@ -345,6 +445,15 @@ class LogoElement extends PolymerElement { onShareDialogClose_() { this.showShareDialog_ = false; } + + /** @private */ + onDurationHeightWidthChange_() { + this.updateStyles({ + '--duration': this.duration_, + '--height': this.height_, + '--width': this.width_, + }); + } } customElements.define(LogoElement.is, LogoElement); diff --git a/chromium/chrome/browser/resources/new_tab_page/most_visited.html b/chromium/chrome/browser/resources/new_tab_page/most_visited.html index 6054974dbde..0b16023d29a 100644 --- a/chromium/chrome/browser/resources/new_tab_page/most_visited.html +++ b/chromium/chrome/browser/resources/new_tab_page/most_visited.html @@ -144,6 +144,7 @@ cr-icon-button { --cr-icon-button-fill-color: var(--icon-button-color); --cr-icon-button-size: 28px; + --cr-icon-button-transition: none; margin: 4px 2px; opacity: 0; position: absolute; diff --git a/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd b/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd index 35e62f674fc..ac16ff94bcf 100644 --- a/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd +++ b/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd @@ -16,7 +16,8 @@ file="new_tab_page.js" type="BINDATA" compress="false" /> <include name="IDR_NEW_TAB_PAGE_APP_JS" file="${root_gen_dir}/chrome/browser/resources/new_tab_page/app.js" - use_base_dir="false" type="BINDATA" compress="false" /> + use_base_dir="false" type="BINDATA" compress="false" + preprocess="true" /> <include name="IDR_NEW_TAB_PAGE_MOST_VISITED_JS" file="${root_gen_dir}/chrome/browser/resources/new_tab_page/most_visited.js" use_base_dir="false" type="BINDATA" compress="false" /> @@ -41,8 +42,8 @@ <include name="IDR_NEW_TAB_PAGE_GRID_JS" file="${root_gen_dir}/chrome/browser/resources/new_tab_page/grid.js" use_base_dir="false" type="BINDATA" compress="false" /> - <include name="IDR_NEW_TAB_UNTRUSTED_IFRAME_JS" - file="${root_gen_dir}/chrome/browser/resources/new_tab_page/untrusted_iframe.js" + <include name="IDR_NEW_TAB_IFRAME_JS" + file="${root_gen_dir}/chrome/browser/resources/new_tab_page/iframe.js" use_base_dir="false" type="BINDATA" compress="false" /> <include name="IDR_NEW_TAB_PAGE_MINI_PAGE_JS" file="${root_gen_dir}/chrome/browser/resources/new_tab_page/mini_page.js" diff --git a/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp b/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp index c8170087238..13fbac2c00f 100644 --- a/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp +++ b/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp @@ -1,70 +1,65 @@ <?xml version="1.0" encoding="UTF-8"?> <grit-part> - <include name="IDR_NEW_TAB_PAGE_SKCOLOR_MOJO_LITE_JS" - file="${root_gen_dir}/skia/public/mojom/skcolor.mojom-lite.js" - use_base_dir="false" type="BINDATA" compress="gzip" /> <include name="IDR_NEW_TAB_PAGE_MOJO_LITE_JS" file="${root_gen_dir}/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom-lite.js" - use_base_dir="false" type="BINDATA" compress="gzip" /> + use_base_dir="false" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_OMNIBOX_MOJO_LITE_JS" file="${root_gen_dir}/chrome/common/search/omnibox.mojom-lite.js" - use_base_dir="false" type="BINDATA" compress="gzip" /> + use_base_dir="false" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_ACCOUNT_CIRCLE_SVG" - file="icons/account_circle.svg" type="BINDATA" compress="gzip" /> + file="icons/account_circle.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_BRUSH_ICON_SVG" - file="icons/brush.svg" type="BINDATA" compress="gzip" /> + file="icons/brush.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_CHECK_CIRCLE_SVG" - file="icons/check_circle.svg" type="BINDATA" compress="gzip" /> + file="icons/check_circle.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_CHEVRON_SVG" - file="icons/chevron.svg" type="BINDATA" compress="gzip" /> + file="icons/chevron.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_GENERIC_GLOBE_SVG" - file="icons/generic_globe.svg" type="BINDATA" compress="gzip" /> + file="icons/generic_globe.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_PENCIL_ICON_SVG" - file="icons/icon_pencil.svg" type="BINDATA" compress="gzip" /> + file="icons/icon_pencil.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_LINK_ICON_SVG" - file="icons/link.svg" type="BINDATA" compress="gzip" /> + file="icons/link.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_BACKGROUNDS_ICON_SVG" - file="icons/backgrounds.svg" type="BINDATA" compress="gzip" /> + file="icons/backgrounds.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_COLORED_HEADER_SVG" - file="icons/colored_header.svg" type="BINDATA" compress="gzip" /> + file="icons/colored_header.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_COLORS_ICON_SVG" - file="icons/colors.svg" type="BINDATA" compress="gzip" /> + file="icons/colors.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_COLORIZE_ICON_SVG" - file="icons/colorize.svg" type="BINDATA" compress="gzip" /> + file="icons/colorize.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_SHORTCUT_CIRCLES_SVG" - file="icons/shortcut_circles.svg" type="BINDATA" compress="gzip" /> + file="icons/shortcut_circles.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_GOOGLE_MIC_SVG" - file="icons/googlemic_clr_24px.svg" type="BINDATA" compress="gzip" /> + file="icons/googlemic_clr_24px.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_MIC_SVG" - file="icons/mic.svg" type="BINDATA" compress="gzip" /> + file="icons/mic.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_COPY_SVG" - file="icons/copy.svg" type="BINDATA" compress="gzip" /> + file="icons/copy.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_FACEBOOK_SVG" - file="icons/facebook.svg" type="BINDATA" compress="gzip" /> + file="icons/facebook.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_TWITTER_SVG" - file="icons/twitter.svg" type="BINDATA" compress="gzip" /> + file="icons/twitter.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_MAIL_SVG" - file="icons/mail.svg" type="BINDATA" compress="gzip" /> + file="icons/mail.svg" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UPLOAD_SVG" file="icons/upload.svg" - type="BINDATA" compress="gzip" /> + type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_NEW_TAB_PAGE_HTML" - file="new_tab_page.html" type="BINDATA" compress="gzip" /> + file="new_tab_page.html" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_SHARED_VARS_CSS" - file="shared_vars.css" type="BINDATA" compress="gzip" /> + file="shared_vars.css" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_ONE_GOOGLE_BAR_HTML" - file="untrusted/one_google_bar.html" type="BINDATA" compress="gzip" /> + file="untrusted/one_google_bar.html" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_ONE_GOOGLE_BAR_JS" - file="untrusted/one_google_bar.js" type="BINDATA" compress="gzip" /> + file="untrusted/one_google_bar.js" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_HTML" - file="untrusted/promo.html" type="BINDATA" compress="gzip" /> + file="untrusted/promo.html" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_JS" - file="untrusted/promo.js" type="BINDATA" compress="gzip" /> + file="untrusted/promo.js" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_IMAGE_HTML" - file="untrusted/image.html" type="BINDATA" compress="gzip" /> + file="untrusted/image.html" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_BACKGROUND_IMAGE_HTML" - file="untrusted/background_image.html" type="BINDATA" compress="gzip" /> + file="untrusted/background_image.html" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_BACKGROUND_IMAGE_JS" - file="untrusted/background_image.js" type="BINDATA" compress="gzip" /> - <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_IFRAME_HTML" - file="untrusted/iframe.html" type="BINDATA" compress="gzip" /> + file="untrusted/background_image.js" type="BINDATA" /> </grit-part> diff --git a/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources_vulcanized.grd b/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources_vulcanized.grd index dea0262271b..c92307069a4 100644 --- a/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources_vulcanized.grd +++ b/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources_vulcanized.grd @@ -14,7 +14,7 @@ <includes> <include name="IDR_NEW_TAB_PAGE_NEW_TAB_PAGE_JS" file="${root_gen_dir}/chrome/browser/resources/new_tab_page/new_tab_page.rollup.js" - use_base_dir="false" type="BINDATA" compress="gzip" + use_base_dir="false" type="BINDATA" preprocess="true" /> <part file="new_tab_page_resources_common.grdp" /> </includes> diff --git a/chromium/chrome/browser/resources/new_tab_page/realbox.html b/chromium/chrome/browser/resources/new_tab_page/realbox.html index 8d3acd17ac7..cd67dd14290 100644 --- a/chromium/chrome/browser/resources/new_tab_page/realbox.html +++ b/chromium/chrome/browser/resources/new_tab_page/realbox.html @@ -132,6 +132,6 @@ result="[[result_]]" selected-match-index="{{selectedMatchIndex_}}" on-result-repaint="onResultRepaint_" on-match-focusin="onMatchFocusin_" on-match-click="onMatchClick_" on-match-remove="onMatchRemove_" - hidden$="[[!matchesAreVisible]]"> + on-header-focusin="onHeaderFocusin_" hidden$="[[!matchesAreVisible]]"> </ntp-realbox-dropdown> </div> diff --git a/chromium/chrome/browser/resources/new_tab_page/realbox.js b/chromium/chrome/browser/resources/new_tab_page/realbox.js index 9ab63767a23..aa9fc080dd0 100644 --- a/chromium/chrome/browser/resources/new_tab_page/realbox.js +++ b/chromium/chrome/browser/resources/new_tab_page/realbox.js @@ -315,6 +315,16 @@ class RealboxElement extends PolymerElement { //============================================================================ /** + * @private + */ + onHeaderFocusin_() { + // The header got focus. Unselect the selected match and clear the input. + assert(this.lastQueriedInput_ === ''); + this.$.matches.unselect(); + this.updateInput_({text: '', inline: ''}); + } + + /** * @param {!Event} e * @private */ diff --git a/chromium/chrome/browser/resources/new_tab_page/realbox_dropdown.html b/chromium/chrome/browser/resources/new_tab_page/realbox_dropdown.html index f8fbddc2cb1..6c088c96d3a 100644 --- a/chromium/chrome/browser/resources/new_tab_page/realbox_dropdown.html +++ b/chromium/chrome/browser/resources/new_tab_page/realbox_dropdown.html @@ -26,16 +26,16 @@ justify-content: space-between; margin-top: 8px; outline: none; - padding-bottom: 4px; + padding-bottom: 6px; padding-inline-end: 16px; padding-inline-start: 12px; - padding-top: 4px; + padding-top: 6px; } .header .text { color: var(--google-grey-refresh-700); cursor: default; - font-size: 13px; + font-size: 14px; font-weight: 500; line-height: 16px; overflow: hidden; diff --git a/chromium/chrome/browser/resources/new_tab_page/realbox_dropdown.js b/chromium/chrome/browser/resources/new_tab_page/realbox_dropdown.js index 7d902a2cdfb..7d7ab9e272f 100644 --- a/chromium/chrome/browser/resources/new_tab_page/realbox_dropdown.js +++ b/chromium/chrome/browser/resources/new_tab_page/realbox_dropdown.js @@ -275,8 +275,10 @@ class RealboxDropdownElement extends PolymerElement { * @private */ onHeaderFocusin_() { - // The header got focus. Unselect the selected match, if any. - this.unselect(); + this.dispatchEvent(new CustomEvent('header-focusin', { + bubbles: true, + composed: true, + })); } /** diff --git a/chromium/chrome/browser/resources/new_tab_page/realbox_match.html b/chromium/chrome/browser/resources/new_tab_page/realbox_match.html index 52f59f29d20..cef7e228029 100644 --- a/chromium/chrome/browser/resources/new_tab_page/realbox_match.html +++ b/chromium/chrome/browser/resources/new_tab_page/realbox_match.html @@ -78,7 +78,7 @@ <ntp-realbox-icon id="icon" match="[[match]]"></ntp-realbox-icon> <div id="container"> <span id="contents" inner-h-t-m-l="[[contentsHtml_]]"></span> - <span id="separator">[[separatorText_]]</span> + <span id="separator" class="dim">[[separatorText_]]</span> <span id="description" inner-h-t-m-l="[[descriptionHtml_]]"></span> </div> <ntp-realbox-button id="remove" tabindex="0" role="button" diff --git a/chromium/chrome/browser/resources/new_tab_page/realbox_match.js b/chromium/chrome/browser/resources/new_tab_page/realbox_match.js index 485ad83f65a..666cfb4e3bb 100644 --- a/chromium/chrome/browser/resources/new_tab_page/realbox_match.js +++ b/chromium/chrome/browser/resources/new_tab_page/realbox_match.js @@ -277,8 +277,7 @@ class RealboxMatchElement extends PolymerElement { * @private */ computeRemoveButtonIsVisible_() { - return this.match && this.match.supportsDeletion && - loadTimeData.getBoolean('suggestionTransparencyEnabled'); + return this.match && this.match.supportsDeletion; } /** diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted/iframe.html b/chromium/chrome/browser/resources/new_tab_page/untrusted/iframe.html deleted file mode 100644 index 43ee39396d2..00000000000 --- a/chromium/chrome/browser/resources/new_tab_page/untrusted/iframe.html +++ /dev/null @@ -1,24 +0,0 @@ -<!doctype html> -<html> - <head> - <style> - html, - body, - iframe { - height: 100%; - width: 100%; - } - - body { - margin: 0 - } - - iframe { - border: none; - } - </style> - </head> - <body> - <iframe src="$i18nRaw{url}"></iframe> - </body> -</html> diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html b/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html index 96d509ff436..20e4c9ecdeb 100644 --- a/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html +++ b/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html @@ -1,5 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}"> +<html dir="$i18n{textdirection}" $i18n{modalOverlays}> <head> <meta charset="utf-8"> <style> diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js b/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js index 416e82acdee..a6bbf5c0de2 100644 --- a/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js +++ b/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js @@ -2,25 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -const oneGoogleBarHeightInPixels = 64; - -/** - * @param {boolean} enabled - * @return {!Promise} - */ -async function enableDarkTheme(enabled) { - if (!window.gbar) { - return; - } - const ogb = await window.gbar.a.bf(); - ogb.pc.call(ogb, enabled ? 1 : 0); -} - /** * The following |messageType|'s are sent to the parent frame: * - loaded: sent on initial load. * - overlaysUpdated: sent when an overlay is updated. The overlay bounding - * rects are included in the |data|. + * rects are included in the |data|. + * - activate/deactivate: When an overlay is open, 'activate' is sent to the + * to ntp-app so it can layer the OneGoogleBar over the NTP content. When + * no overlays are open, 'deactivate' is sent to ntp-app so the NTP + * content can be on top. The top bar of the OneGoogleBar is always on + * top. * @param {string} messageType * @param {Object} data */ @@ -33,91 +24,206 @@ function postMessage(messageType, data) { 'chrome://new-tab-page'); } -const overlays = new Set(); +// Object that exposes: +// - |getEnabled()|: returns whether dark theme is enabled. +// - |setEnabled(value)|: updates whether dark theme is enabled using the +// OneGoogleBar API. +const darkTheme = (() => { + let enabled = false; -function sendOverlayUpdate() { - // Remove overlays detached from DOM or elements in a parent overlay. - Array.from(overlays).forEach(overlay => { - if (!overlay.parentElement) { - overlays.delete(overlay); + /** @return {boolean} */ + const getEnabled = () => enabled; + + /** + * @param {boolean} value + * @return {!Promise} + */ + const setEnabled = async value => { + if (!window.gbar) { return; } - let parent = overlay.parentElement; - while (parent) { - if (overlays.has(parent)) { - overlays.delete(overlay); - return; - } - parent = parent.parentElement; + enabled = value; + const ogb = await window.gbar.a.bf(); + ogb.pc.call(ogb, enabled ? 1 : 0); + }; + + return {getEnabled, setEnabled}; +})(); + +// Object that exposes: +// - |track()|: sets up MutationObserver to track element visibility changes. +// - |update(potentialNewOverlays)|: determines visibility of tracked elements +// and sends an update to the top frame about element visibility. +const overlayUpdater = (() => { + const modalOverlays = document.documentElement.hasAttribute('modal-overlays'); + let shouldUndoDarkTheme = false; + + /** @type {!Set<!Element>} */ + const overlays = new Set(); + /** @type {!Array<!DOMRect>} */ + let lastOverlayRects = []; + /** @type {number} */ + let elementsTransitioningCount = 0; + /** @type {?number} */ + let updateIntervalId = null; + /** @type {boolean} */ + let initialElementsAdded = false; + + const transitionStart = () => { + elementsTransitioningCount++; + if (!updateIntervalId) { + updateIntervalId = setInterval(() => { + update([]); + }); } - }); - // Check if an overlay and its parents are visible. - const overlayRects = - Array.from(overlays) - .filter(overlay => { - if (window.getComputedStyle(overlay).visibility === 'hidden') { - return false; - } - let current = overlay; - while (current) { - if (window.getComputedStyle(current).display === 'none') { - return false; - } - current = current.parentElement; - } - return true; - }) - .map(el => el.getBoundingClientRect()); - postMessage('overlaysUpdated', overlayRects); -} + }; + + const transitionStop = () => { + if (elementsTransitioningCount > 0) { + elementsTransitioningCount--; + } + if (updateIntervalId && elementsTransitioningCount === 0) { + clearInterval(updateIntervalId); + updateIntervalId = null; + } + }; + + /** @param {!Element} potentialNewOverlays */ + const addOverlay = overlay => { + // If an overlay starts a transition, the updated bounding rects need to + // be sent to the top frame during the transition. The MutationObserver + // will only handle new elements and changes to the element attributes. + overlay.addEventListener('animationstart', transitionStart); + overlay.addEventListener('animationend', transitionStop); + overlay.addEventListener('animationcancel', transitionStop); + overlay.addEventListener('transitionstart', transitionStart); + overlay.addEventListener('transitionend', transitionStop); + overlay.addEventListener('transitioncancel', transitionStop); + // Update links that are loaded dynamically to ensure target is "_blank" + // or "_top". + // TODO(crbug.com/1039913): remove after OneGoogleBar links are updated. + overlay.parentElement.querySelectorAll('a').forEach(el => { + if (el.target !== '_blank' && el.target !== '_top') { + el.target = '_top'; + } + }); + overlays.add(overlay); + }; -function trackOverlayState() { - const observer = new MutationObserver(mutations => { - // After loaded, there could exist overlays that are shown, but not mutated. - // Add all elements that could be an overlay. The children of the actual - // overlay element are removed before sending any overlay update message. - if (overlays.size === 0) { + /** @param {!Array<!Element>} potentialNewOverlays */ + const update = potentialNewOverlays => { + const barRect = document.body.querySelector('#gb').getBoundingClientRect(); + if (barRect.bottom === 0) { + return; + } + // After loaded, there could exist overlays that are shown, but not + // mutated. Add all elements that could be an overlay. The children of the + // actual overlay element are removed before sending any overlay update + // message. + if (!modalOverlays && !initialElementsAdded) { + initialElementsAdded = true; Array.from(document.body.querySelectorAll('*')).forEach(el => { - if (el.offsetTop + el.offsetHeight > oneGoogleBarHeightInPixels) { - overlays.add(el); - } + potentialNewOverlays.push(el); }); } - // Add any mutated element that is an overlay to |overlays|. - mutations.forEach(({target}) => { - if (target.id === 'gb' || target.tagName === 'BODY' || - overlays.has(target)) { - return; + Array.from(potentialNewOverlays).forEach(overlay => { + const rect = overlay.getBoundingClientRect(); + if (overlay.parentElement && rect.width > 0 && + rect.bottom > barRect.bottom) { + addOverlay(overlay); } - if (target.offsetTop + target.offsetHeight > oneGoogleBarHeightInPixels) { - overlays.add(target); + }); + // Remove overlays detached from DOM. + Array.from(overlays).forEach(overlay => { + if (!overlay.parentElement) { + overlays.delete(overlay); } - // Update links that are loaded dynamically to ensure target is "_blank" - // or "_top". - // TODO(crbug.com/1039913): remove after OneGoogleBar links are updated. - if (target.parentElement) { - target.parentElement.querySelectorAll('a').forEach(el => { - if (el.target !== '_blank' && el.target !== '_top') { - el.target = '_top'; - } - }); + }); + // Check if an overlay and its parents are visible. + const overlayRects = []; + overlays.forEach(overlay => { + const {display, visibility} = window.getComputedStyle(overlay); + const rect = overlay.getBoundingClientRect(); + if (display !== 'none' && visibility !== 'hidden' && + rect.bottom > barRect.bottom) { + overlayRects.push(rect); } }); - sendOverlayUpdate(); - }); - observer.observe( - document, {attributes: true, childList: true, subtree: true}); -} + if (!modalOverlays) { + overlayRects.push(barRect); + const noChange = overlayRects.length === lastOverlayRects.length && + lastOverlayRects.every((rect, i) => { + const newRect = overlayRects[i]; + return newRect.left === rect.left && newRect.top === rect.top && + newRect.right === rect.right && newRect.bottom === rect.bottom; + }); + lastOverlayRects = overlayRects; + if (noChange) { + return; + } + postMessage('overlaysUpdated', overlayRects); + return; + } + const overlayShown = overlayRects.length > 0; + postMessage(overlayShown ? 'activate' : 'deactivate'); + // If the overlays are modal, a dark backdrop is displayed below the + // OneGoogleBar iframe. The dark theme for the OneGoogleBar is then enabled + // for better visibility. + if (overlayShown) { + if (!darkTheme.getEnabled()) { + shouldUndoDarkTheme = true; + darkTheme.setEnabled(true); + } + } else if (shouldUndoDarkTheme) { + shouldUndoDarkTheme = false; + darkTheme.setEnabled(false); + } + }; + + const track = () => { + const observer = new MutationObserver(mutations => { + const potentialNewOverlays = []; + // Add any mutated element that is an overlay to |overlays|. + mutations.forEach(({target}) => { + if (overlays.has(target) || !target.parentElement) { + return; + } + // When overlays are modal, the tooltips should not be treated like an + // overlay. + if (modalOverlays && target.parentElement.tagName === 'BODY') { + return; + } + potentialNewOverlays.push(target); + }); + update(potentialNewOverlays); + }); + observer.observe(document.body, { + attributes: true, + childList: true, + subtree: true, + }); + }; + + return {track, update}; +})(); window.addEventListener('message', ({data}) => { if (data.type === 'enableDarkTheme') { - enableDarkTheme(data.enabled); + darkTheme.setEnabled(data.enabled); } }); // Need to send overlay updates on resize because overlay bounding rects are // absolutely positioned. -window.addEventListener('resize', sendOverlayUpdate); +window.addEventListener('resize', () => { + overlayUpdater.update([]); +}); + +// When the account overlay is shown, it does not close on blur. It does close +// when clicking the body. +window.addEventListener('blur', () => { + document.body.click(); +}); document.addEventListener('DOMContentLoaded', () => { // TODO(crbug.com/1039913): remove after OneGoogleBar links are updated. @@ -127,6 +233,7 @@ document.addEventListener('DOMContentLoaded', () => { el.target = '_top'; } }); + modalOverlays = document.documentElement.hasAttribute('modal-overlays'); postMessage('loaded'); - trackOverlayState(); + overlayUpdater.track(); }); diff --git a/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.html b/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.html index 20e0a48c862..bd8484300bc 100644 --- a/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.html +++ b/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.html @@ -1,4 +1,4 @@ -<style> +<style include="cr-icons"> :host { --receiving-audio-color: var(--google-red-refresh-500); --speak-shown-duration: 2s; @@ -28,27 +28,10 @@ } #closeButton { - background: none; - border: none; - color: var(--ntp-secondary-text-color); - cursor: pointer; - font-family: inherit; - font-size: 26px; - height: 15px; - line-height: 0; - outline: none; - padding: 0; + --cr-icon-button-fill-color: var(--ntp-secondary-text-color); + margin: 0; position: absolute; top: 16px; - width: 15px; - } - - #closeButton:hover { - color: var(--ntp-secondary-text-hover-color); - } - - :host-context(.focus-outline-visible) #closeButton:focus { - box-shadow: var(--ntp-focus-shadow); } :host-context([dir='ltr']) #closeButton { @@ -188,8 +171,12 @@ background-color: white; } </style> -<dialog id="dialog" on-close="onOverlayClose_" on-click="onOverlayClick_"> - <button id="closeButton" tabindex="0" title="$i18n{close}">×</button> +<dialog id="dialog" on-close="onOverlayClose_" on-click="onOverlayClick_" + on-keydown="onOverlayKeydown_"> + <!-- Purely exists to capture focus upon opening the dialog. --> + <div tabindex="-1"></div> + <cr-icon-button id="closeButton" class="icon-clear" title="$i18n{close}"> + </cr-icon-button> <div id="content"> <iron-selector id="texts" selected="[[getText_(state_)]]" attr-for-selected="text" fallback-selection="none" aria-live="polite" @@ -200,32 +187,34 @@ <div id="speak">$i18n{speak}</div> <div id="listening">$i18n{listening}</div> </div> - <div text="result"> + <div text="result" aria-hidden="true"> <span id="finalResult">[[finalResult_]]</span> <span>[[interimResult_]]</span> </div> <div text="error"> - <iron-pages id="errors" selected="[[error_]]" attr-for-selected="error" - fallback-selection="7"> - <span error="1">$i18n{noVoice}</span> - <span error="2">$i18n{audioError}</span> - <span error="3">$i18n{networkError}</span> - <span error="4">$i18n{permissionError}</span> - <span error="5">$i18n{languageError}</span> - <span error="6">$i18n{noTranslation}</span> - <span error="7">$i18n{otherError}</span> + <iron-pages id="errors" selected="[[getErrorText_(error_)]]" + attr-for-selected="error" fallback-selection="other"> + <span error="no-speech">$i18n{noVoice}</span> + <span error="audio-capture">$i18n{audioError}</span> + <span error="network">$i18n{networkError}</span> + <span error="not-allowed">$i18n{permissionError}</span> + <span error="language-not-supported">$i18n{languageError}</span> + <span error="no-match">$i18n{noTranslation}</span> + <span error="other">$i18n{otherError}</span> </iron-pages> <iron-pages id="errorLinks" selected="[[getErrorLink_(error_)]]" attr-for-selected="link" fallback-selection="none"> <span link="none"></span> - <a link="learn-more" target="_blank" href="[[helpUrl_]]"><!-- + <a link="learn-more" target="_blank" href="[[helpUrl_]]" + on-click="onLearnMoreClick_" on-keydown="onLinkKeydown_"><!-- -->$i18n{learnMore} </a> - <a link="details" target="_blank" href="[[helpUrl_]]"><!-- + <a link="details" target="_blank" href="[[helpUrl_]]" + on-keydown="onLinkKeydown_"><!-- -->$i18n{details} </a> <a link="try-again" id="retryLink" href="#" - on-click="onRetryClick_"><!-- + on-click="onTryAgainClick_" on-keydown="onLinkKeydown_"><!-- -->$i18n{tryAgain} </a> </iron-pages> @@ -238,7 +227,7 @@ <div id="micVolumeCutout"> </div> </div> - <cr-button id="micButton" on-click="onRetryClick_"> + <cr-button id="micButton" on-click="onMicClick_"> <div id="micIcon"></div> </cr-button> </div> diff --git a/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.js b/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.js index 278fac75e41..6db0f40b9ea 100644 --- a/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.js +++ b/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.js @@ -5,6 +5,7 @@ import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js'; import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -90,20 +91,9 @@ const State = { RESULT_FINAL: 5, }; -/** - * The set of possible recognition errors. - * @enum {!number} - */ -const Error = { - ABORTED: 0, - NO_SPEECH: 1, - AUDIO_CAPTURE: 2, - NETWORK: 3, - NOT_ALLOWED: 4, - LANGUAGE_NOT_SUPPORTED: 5, - NO_MATCH: 6, - OTHER: 7, -}; + +/** @typedef {newTabPage.mojom.VoiceSearchError} */ +const Error = newTabPage.mojom.VoiceSearchError; /** * Returns the error type based on the error string received from the webkit @@ -125,8 +115,11 @@ function toError(webkitError) { case 'no-speech': return Error.NO_SPEECH; case 'not-allowed': - case 'service-not-allowed': return Error.NOT_ALLOWED; + case 'service-not-allowed': + return Error.SERVICE_NOT_ALLOWED; + case 'bad-grammar': + return Error.BAD_GRAMMAR; default: return Error.OTHER; } @@ -201,6 +194,8 @@ class VoiceSearchOverlayElement extends PolymerElement { constructor() { super(); + /** @private {newTabPage.mojom.PageHandlerRemote} */ + this.pageHandler_ = BrowserProxy.getInstance().handler; /** @private {webkitSpeechRecognition} */ this.voiceRecognition_ = new webkitSpeechRecognition(); this.voiceRecognition_.continuous = false; @@ -243,19 +238,71 @@ class VoiceSearchOverlayElement extends PolymerElement { /** @private */ onOverlayClick_() { this.$.dialog.close(); + this.pageHandler_.onVoiceSearchAction( + newTabPage.mojom.VoiceSearchAction.CLOSE_OVERLAY); + } + + /** + * Handles <ENTER> or <SPACE> to trigger a query if we have recognized speech. + * @param {KeyboardEvent} e + * @private + */ + onOverlayKeydown_(e) { + if (['Enter', ' '].includes(e.key) && this.finalResult_) { + this.onFinalResult_(); + } else if (e.key === 'Escape') { + this.onOverlayClick_(); + } + } + + /** + * Handles <ENTER> or <SPACE> to simulate click. + * @param {KeyboardEvent} e + * @private + */ + onLinkKeydown_(e) { + if (!['Enter', ' '].includes(e.key)) { + return; + } + // Otherwise, we may trigger overlay-wide keyboard shortcuts. + e.stopPropagation(); + // Otherwise, we open the link twice. + e.preventDefault(); + e.target.click(); + } + + /** @private */ + onLearnMoreClick_() { + this.pageHandler_.onVoiceSearchAction( + newTabPage.mojom.VoiceSearchAction.SUPPORT_LINK_CLICKED); + } + + /** + * @param {!Event} e + * @private + */ + onTryAgainClick_(e) { + // Otherwise, we close the overlay. + e.stopPropagation(); + this.start(); + this.pageHandler_.onVoiceSearchAction( + newTabPage.mojom.VoiceSearchAction.TRY_AGAIN_LINK); } /** * @param {!Event} e * @private */ - onRetryClick_(e) { + onMicClick_(e) { if (this.state_ !== State.ERROR_RECEIVED || this.error_ !== Error.NO_MATCH) { return; } + // Otherwise, we close the overlay. e.stopPropagation(); this.start(); + this.pageHandler_.onVoiceSearchAction( + newTabPage.mojom.VoiceSearchAction.TRY_AGAIN_MIC_BUTTON); } /** @private */ @@ -286,8 +333,9 @@ class VoiceSearchOverlayElement extends PolymerElement { */ resetErrorTimer_(duration) { BrowserProxy.getInstance().clearTimeout(this.timerId_); - this.timerId_ = BrowserProxy.getInstance().setTimeout( - this.onOverlayClick_.bind(this), duration); + this.timerId_ = BrowserProxy.getInstance().setTimeout(() => { + this.$.dialog.close(); + }, duration); } /** @private */ @@ -376,6 +424,8 @@ class VoiceSearchOverlayElement extends PolymerElement { const queryUrl = new URL('/search', loadTimeData.getString('googleBaseUrl')); queryUrl.search = searchParams.toString(); + this.pageHandler_.onVoiceSearchAction( + newTabPage.mojom.VoiceSearchAction.QUERY_SUBMITTED); BrowserProxy.getInstance().navigate(queryUrl.href); } @@ -406,6 +456,7 @@ class VoiceSearchOverlayElement extends PolymerElement { * @private */ onError_(error) { + this.pageHandler_.onVoiceSearchError(error); if (error === Error.ABORTED) { // We are in the process of closing voice search. return; @@ -457,12 +508,39 @@ class VoiceSearchOverlayElement extends PolymerElement { * @return {string} * @private */ + getErrorText_() { + switch (this.error_) { + case Error.NO_SPEECH: + return 'no-speech'; + case Error.AUDIO_CAPTURE: + return 'audio-capture'; + case Error.NETWORK: + return 'network'; + case Error.NOT_ALLOWED: + case Error.SERVICE_NOT_ALLOWED: + return 'not-allowed'; + case Error.LANGUAGE_NOT_SUPPORTED: + return 'language-not-supported'; + case Error.NO_MATCH: + return 'no-match'; + case Error.ABORTED: + case Error.OTHER: + default: + return 'other'; + } + } + + /** + * @return {string} + * @private + */ getErrorLink_() { switch (this.error_) { case Error.NO_SPEECH: case Error.AUDIO_CAPTURE: return 'learn-more'; case Error.NOT_ALLOWED: + case Error.SERVICE_NOT_ALLOWED: return 'details'; case Error.NO_MATCH: return 'try-again'; diff --git a/chromium/chrome/browser/resources/omnibox/resources.grd b/chromium/chrome/browser/resources/omnibox/resources.grd index 349526f27ab..273065f153d 100644 --- a/chromium/chrome/browser/resources/omnibox/resources.grd +++ b/chromium/chrome/browser/resources/omnibox/resources.grd @@ -14,53 +14,41 @@ file="omnibox.html" flattenhtml="true" allowexternalscript="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OMNIBOX_POPUP_HTML" file="omnibox_popup.html" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OMNIBOX_CSS" file="omnibox.css" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OMNIBOX_INPUT_CSS" file="omnibox_input.css" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OUTPUT_RESULTS_GROUP_CSS" file="output_results_group.css" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OMNIBOX_OUTPUT_COLUMN_WIDTHS_CSS" file="omnibox_output_column_widths.css" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OMNIBOX_ELEMENT_JS" file="omnibox_element.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OMNIBOX_INPUT_JS" file="omnibox_input.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OMNIBOX_OUTPUT_JS" file="omnibox_output.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OMNIBOX_POPUP_JS" - file="omnibox_popup.js" - type="BINDATA" - compress="gzip" /> + file="omnibox_popup.js" + type="BINDATA" /> <include name="IDR_OMNIBOX_JS" file="omnibox.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OMNIBOX_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\omnibox\omnibox.mojom-lite.js" use_base_dir="false" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/optimize_webui.gni b/chromium/chrome/browser/resources/optimize_webui.gni index bfc1f5a4121..01db4694669 100644 --- a/chromium/chrome/browser/resources/optimize_webui.gni +++ b/chromium/chrome/browser/resources/optimize_webui.gni @@ -103,5 +103,16 @@ template("unpak") { "--pak_file", rebase_path("$target_gen_dir/${invoker.pak_file}", root_build_dir), ] + + if (defined(invoker.pak_base_dir)) { + args += [ + "--pak_base_dir", + rebase_path("$target_gen_dir/${invoker.pak_base_dir}", root_build_dir), + ] + } + + if (defined(invoker.excludes)) { + args += [ "--excludes" ] + invoker.excludes + } } } diff --git a/chromium/chrome/browser/resources/optimize_webui.py b/chromium/chrome/browser/resources/optimize_webui.py index 388cb640460..30ffbf7f343 100755 --- a/chromium/chrome/browser/resources/optimize_webui.py +++ b/chromium/chrome/browser/resources/optimize_webui.py @@ -58,25 +58,29 @@ _POLYMER_PATH = os.path.join( # These files are already combined and minified. _BASE_EXCLUDES = [ - # Common excludes for both Polymer 2 and 3. - 'chrome://resources/polymer/v1_0/web-animations-js/' + - 'web-animations-next-lite.min.js', - 'chrome://resources/css/roboto.css', - 'chrome://resources/css/text_defaults.css', - 'chrome://resources/css/text_defaults_md.css', - 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html', - # Excludes applying only to Polymer 2. 'chrome://resources/html/polymer.html', 'chrome://resources/polymer/v1_0/polymer/polymer.html', 'chrome://resources/polymer/v1_0/polymer/polymer-micro.html', 'chrome://resources/polymer/v1_0/polymer/polymer-mini.html', - 'chrome://resources/js/load_time_data.js', + 'chrome://resources/js/load_time_data.js' +] +for excluded_file in [ + # Common excludes for both Polymer 2 and 3. + 'resources/polymer/v1_0/web-animations-js/web-animations-next-lite.min.js', + 'resources/css/roboto.css', + 'resources/css/text_defaults.css', + 'resources/css/text_defaults_md.css', + 'resources/mojo/mojo/public/js/mojo_bindings_lite.html', # Excludes applying only to Polymer 3. - 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js', - 'chrome://resources/js/load_time_data.m.js', -] + 'resources/polymer/v3_0/polymer/polymer_bundled.min.js', + 'resources/js/load_time_data.m.js', +]: + # Exclude both the chrome://resources form and the scheme-relative form for + # files used in Polymer 3. + _BASE_EXCLUDES.append("chrome://" + excluded_file) + _BASE_EXCLUDES.append("//" + excluded_file) _VULCANIZE_BASE_ARGS = [ '--inline-css', @@ -85,15 +89,19 @@ _VULCANIZE_BASE_ARGS = [ '--strip-comments', ] -_URL_MAPPINGS = [ - ('chrome://resources/cr_components/', _CR_COMPONENTS_PATH), - ('chrome://resources/cr_elements/', _CR_ELEMENTS_PATH), - ('chrome://resources/css/', _CSS_RESOURCES_PATH), - ('chrome://resources/html/', _HTML_RESOURCES_PATH), - ('chrome://resources/js/', _JS_RESOURCES_PATH), - ('chrome://resources/polymer/v1_0/', _POLYMER_PATH), - ('chrome://resources/images/', _IMAGES_RESOURCES_PATH) -] +_URL_MAPPINGS = [] +for (redirect_url, file_path) in [ + ('resources/cr_components/', _CR_COMPONENTS_PATH), + ('resources/cr_elements/', _CR_ELEMENTS_PATH), + ('resources/css/', _CSS_RESOURCES_PATH), + ('resources/html/', _HTML_RESOURCES_PATH), + ('resources/js/', _JS_RESOURCES_PATH), + ('resources/polymer/v1_0/', _POLYMER_PATH), + ('resources/images/', _IMAGES_RESOURCES_PATH), +]: + # Redirect both the chrome://resources form and the scheme-relative form. + _URL_MAPPINGS.append(('chrome://' + redirect_url, file_path)) + _URL_MAPPINGS.append(('//' + redirect_url, file_path)) _VULCANIZE_REDIRECT_ARGS = list(itertools.chain.from_iterable(map( @@ -123,7 +131,7 @@ def _update_dep_file(in_folder, args, manifest): # Add a slash in front of every dependency that is not a chrome:// URL, so # that we can map it to the correct source file path below. request_list = map( - lambda dep: '/' + dep if not dep.startswith('chrome://') else dep, + lambda dep: '/' + dep if not (dep.startswith('chrome://') or dep.startswith('//')) else dep, request_list) # Undo the URL mappings applied by vulcanize to get file paths relative to @@ -138,7 +146,7 @@ def _update_dep_file(in_folder, args, manifest): # If the input was a folder holding an unpacked .pak file, the generated # depfile should not list files already in the .pak file. - if args.input.endswith('.unpak'): + if args.input.endswith('unpak'): filter_url = args.input deps = [d for d in deps if not d.startswith(filter_url)] @@ -210,9 +218,10 @@ def _bundle_v3(tmp_out_dir, in_path, out_path, manifest_out_path, args, # arbitrary names? bundled_paths = [] for index, js_file in enumerate(args.js_module_in_files): - expected_name = '%s.rollup.js' % js_file[:-len('.js')] + base_file_name = os.path.basename(js_file) + expected_name = '%s.rollup.js' % base_file_name[:-len('.js')] assert args.js_out_files[index] == expected_name, \ - 'Output file corresponding to %s should be named %s.rollup.js' % \ + 'Output file corresponding to %s should be named %s' % \ (js_file, expected_name) bundled_paths.append(os.path.join(tmp_out_dir, expected_name)) diff --git a/chromium/chrome/browser/resources/pdf/BUILD.gn b/chromium/chrome/browser/resources/pdf/BUILD.gn index c975fd597e2..02cef40417b 100644 --- a/chromium/chrome/browser/resources/pdf/BUILD.gn +++ b/chromium/chrome/browser/resources/pdf/BUILD.gn @@ -3,6 +3,22 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +group("web_components") { + public_deps = [ + ":web_components_local", + "elements:web_components", + ] +} + +html_to_js("web_components_local") { + js_files = [ + "pdf_viewer.js", + "pdf_viewer_pp.js", + "pdf_viewer_shared_style.js", + ] +} group("closure_compile") { deps = [ @@ -32,10 +48,12 @@ js_library("constants") { } js_library("gesture_detector") { + deps = [ "//ui/webui/resources/js/cr:event_target.m" ] } js_library("open_pdf_params_parser") { deps = [ ":constants" ] + externs_list = [ "$externs_path/pending.js" ] } js_library("pdf_scripting_api") { @@ -83,32 +101,61 @@ js_library("toolbar_manager") { ] } -js_library("controller") { +js_library("ink_controller") { deps = [ ":annotation_tool", + ":controller", + ":viewport", + "//ui/webui/resources/js/cr:event_target.m", + ] +} + +js_library("controller") { + deps = [ ":viewport", "elements:viewer-pdf-toolbar", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", "//ui/webui/resources/js:promise_resolver.m", - "//ui/webui/resources/js:util.m", "//ui/webui/resources/js/cr:event_target.m", ] } +js_library("pdf_viewer_base") { + deps = [ + ":browser_api", + ":constants", + ":controller", + ":metrics", + ":pdf_scripting_api", + ":pdf_viewer_utils", + ":viewport", + ":viewport_scroller", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:event_tracker.m", + "//ui/webui/resources/js:load_time_data.m", + "//ui/webui/resources/js:promise_resolver.m", + "//ui/webui/resources/js:util.m", + ] + externs_list = [ "$externs_path/resources_private.js" ] +} + js_library("pdf_viewer") { deps = [ ":bookmark_type", + ":browser_api", ":constants", ":controller", + ":ink_controller", ":metrics", ":navigator", ":pdf_scripting_api", + ":pdf_viewer_base", + ":pdf_viewer_utils", ":toolbar_manager", ":viewport", - ":viewport_scroller", "elements:viewer-error-screen", - "elements:viewer-page-indicator", "elements:viewer-password-screen", "elements:viewer-pdf-toolbar", "elements:viewer-zoom-toolbar", @@ -121,19 +168,39 @@ js_library("pdf_viewer") { externs_list = [ "$externs_path/resources_private.js" ] } -js_library("main_util") { +js_library("pdf_viewer_utils") { deps = [ - ":browser_api", - ":pdf_viewer", + ":controller", + ":viewport", ] } -js_library("main") { - deps = [ ":main_util" ] +js_library("pdf_viewer_pp") { + deps = [ + ":constants", + ":controller", + ":pdf_scripting_api", + ":pdf_viewer_base", + ":pdf_viewer_utils", + ":toolbar_manager", + ":viewport", + "elements:viewer-error-screen", + "elements:viewer-page-indicator", + "elements:viewer-zoom-toolbar", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:event_tracker.m", + "//ui/webui/resources/js:load_time_data.m", + "//ui/webui/resources/js:promise_resolver.m", + "//ui/webui/resources/js:util.m", + ] + externs_list = [ "$externs_path/resources_private.js" ] } -js_library("main_pp") { - deps = [ ":main_util" ] +js_library("main") { + deps = [ + ":browser_api", + ":pdf_viewer", + ] } js_type_check("pdf_resources") { @@ -144,14 +211,16 @@ js_type_check("pdf_resources") { ":constants", ":controller", ":gesture_detector", + ":ink_controller", ":main", - ":main_pp", - ":main_util", ":metrics", ":navigator", ":open_pdf_params_parser", ":pdf_scripting_api", ":pdf_viewer", + ":pdf_viewer_base", + ":pdf_viewer_pp", + ":pdf_viewer_utils", ":toolbar_manager", ":viewport", ":viewport_scroller", diff --git a/chromium/chrome/browser/resources/pdf/annotation_tool.js b/chromium/chrome/browser/resources/pdf/annotation_tool.js index 5e887b048b7..e8fa6e74d6c 100644 --- a/chromium/chrome/browser/resources/pdf/annotation_tool.js +++ b/chromium/chrome/browser/resources/pdf/annotation_tool.js @@ -9,7 +9,7 @@ * @typedef {{ * tool: string, * size: number, - * color: (string|null), + * color: (string|undefined), * }} */ let AnnotationTool; diff --git a/chromium/chrome/browser/resources/pdf/browser_api.js b/chromium/chrome/browser/resources/pdf/browser_api.js index 53ceeef1da9..5e2fb44cdc3 100644 --- a/chromium/chrome/browser/resources/pdf/browser_api.js +++ b/chromium/chrome/browser/resources/pdf/browser_api.js @@ -28,7 +28,6 @@ function lookupDefaultZoom(streamInfo) { * Returns a promise that will resolve to the initial zoom factor * upon starting the plugin. This may differ from the default zoom * if, for example, the page is zoomed before the plugin is run. - * * @param {!Object} streamInfo The stream object pointing to the data contained * in the PDF. * @return {Promise<number>} A promise that will resolve to the initial zoom @@ -46,9 +45,7 @@ function lookupInitialZoom(streamInfo) { }); } -/** - * A class providing an interface to the browser. - */ +// A class providing an interface to the browser. export class BrowserApi { /** * @param {!Object} streamInfo The stream object which points to the data @@ -90,7 +87,6 @@ export class BrowserApi { /** * Sets the browser zoom. - * * @param {number} zoom The zoom factor to send to the browser. * @return {Promise} A promise that will be resolved when the browser zoom * has been updated. @@ -104,23 +100,17 @@ export class BrowserApi { }); } - /** - * @return {number} The default browser zoom factor. - */ + /** @return {number} The default browser zoom factor. */ getDefaultZoom() { return this.defaultZoom_; } - /** - * @return {number} The initial browser zoom factor. - */ + /** @return {number} The initial browser zoom factor. */ getInitialZoom() { return this.initialZoom_; } - /** - * @return {BrowserApi.ZoomBehavior} How to manage zoom. - */ + /** @return {BrowserApi.ZoomBehavior} How to manage zoom. */ getZoomBehavior() { return this.zoomBehavior_; } @@ -160,7 +150,6 @@ BrowserApi.ZoomBehavior = { /** * Creates a BrowserApi for an extension running as a mime handler. - * * @return {!Promise<!BrowserApi>} A promise to a BrowserApi instance * constructed using the mimeHandlerPrivate API. */ @@ -197,7 +186,6 @@ function createBrowserApiForMimeHandlerView() { /** * Creates a BrowserApi instance for an extension not running as a mime handler. - * * @return {!Promise<!BrowserApi>} A promise to a BrowserApi instance * constructed from the URL. */ diff --git a/chromium/chrome/browser/resources/pdf/constants.js b/chromium/chrome/browser/resources/pdf/constants.js index 70da3e827d7..475061b73ae 100644 --- a/chromium/chrome/browser/resources/pdf/constants.js +++ b/chromium/chrome/browser/resources/pdf/constants.js @@ -21,3 +21,14 @@ export const TwoUpViewAction = { TWO_UP_VIEW_ENABLE: 'two-up-view-enable', TWO_UP_VIEW_DISABLE: 'two-up-view-disable', }; + +/** + * Enumeration of save message request types. Must Match SaveRequestType in + * pdf/out_of_process_instance.h. + * @enum {number} + */ +export const SaveRequestType = { + ANNOTATION: 0, + ORIGINAL: 1, + EDITED: 2, +}; diff --git a/chromium/chrome/browser/resources/pdf/controller.js b/chromium/chrome/browser/resources/pdf/controller.js index 9eccd835645..95c02f1fa0d 100644 --- a/chromium/chrome/browser/resources/pdf/controller.js +++ b/chromium/chrome/browser/resources/pdf/controller.js @@ -6,8 +6,8 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js'; -import {$} from 'chrome://resources/js/util.m.js'; +import {SaveRequestType} from './constants.js'; import {PartialPoint, Point, Viewport} from './viewport.js'; /** @typedef {{ type: string }} */ @@ -45,25 +45,6 @@ let EmailMessageData; */ export let PrintPreviewParams; -// Note: Redefining this type here, to work around the fact that ink externs -// are only available on Chrome OS, so the targets that contain them cannot be -// built on other platforms. -// TODO (rbpotter): Break InkController into its own file that is only included -// on Chrome OS. - -/** - * @typedef {{ - * setAnnotationTool: function(AnnotationTool):void, - * viewportChanged: function():void, - * saveDocument: function():!Promise, - * undo: function():void, - * redo: function():void, - * load: function(string, !ArrayBuffer):!Promise, - * viewport: !Viewport, - * }} - */ -let ViewerInkHostElement; - /** * Creates a cryptographically secure pseudorandom 128-bit token. * @return {string} The generated token as a hex string. @@ -105,12 +86,13 @@ export class ContentController { /** * Requests that the current document be saved. - * @param {boolean} requireResult whether a response is required, otherwise - * the controller may save the document to disk internally. + * @param {!SaveRequestType} requestType The type of save request. If + * ANNOTATION, a response is required, otherwise the controller may save + * the document to disk internally. * @return {Promise<{fileName: string, dataToSave: ArrayBuffer}>} * @abstract */ - save(requireResult) {} + save(requestType) {} /** * Loads PDF document from `data` activates UI. @@ -128,110 +110,9 @@ export class ContentController { unload() {} } -/** - * Controller for annotation mode, on Chrome OS only. Fires the following events - * from its event target: - * has-unsaved-changes: Fired to indicate there are ink annotations that have - * not been saved. - * set-annotation-undo-state: Contains information about whether undo or redo - * options are available. - */ -export class InkController extends ContentController { - /** @param {!Viewport} viewport */ - constructor(viewport) { - super(); - - /** @private {!Viewport} */ - this.viewport_ = viewport; - - /** @private {?ViewerInkHostElement} */ - this.inkHost_ = null; - - /** @private {!EventTarget} */ - this.eventTarget_ = new EventTarget(); - - /** @type {?AnnotationTool} */ - this.tool_ = null; - } - - /** @return {!EventTarget} */ - getEventTarget() { - return this.eventTarget_; - } - - /** @param {AnnotationTool} tool */ - setAnnotationTool(tool) { - this.tool_ = tool; - if (this.inkHost_) { - this.inkHost_.setAnnotationTool(tool); - } - } - - /** @override */ - rotateClockwise() { - // TODO(dstockwell): implement rotation - } - - /** @override */ - rotateCounterclockwise() { - // TODO(dstockwell): implement rotation - } - - /** @override */ - setTwoUpView(enableTwoUpView) { - // TODO(dstockwell): Implement two up view. - } - - /** @override */ - viewportChanged() { - this.inkHost_.viewportChanged(); - } - - /** @override */ - save(requireResult) { - return this.inkHost_.saveDocument(); - } - - /** @override */ - undo() { - this.inkHost_.undo(); - } - - /** @override */ - redo() { - this.inkHost_.redo(); - } - - /** @override */ - load(filename, data) { - if (!this.inkHost_) { - const inkHost = document.createElement('viewer-ink-host'); - $('content').appendChild(inkHost); - this.inkHost_ = /** @type {!ViewerInkHostElement} */ (inkHost); - this.inkHost_.viewport = this.viewport_; - inkHost.addEventListener('stroke-added', e => { - this.eventTarget_.dispatchEvent(new CustomEvent('has-unsaved-changes')); - }); - inkHost.addEventListener('undo-state-changed', e => { - this.eventTarget_.dispatchEvent( - new CustomEvent('set-annotation-undo-state', {detail: e.detail})); - }); - } - return this.inkHost_.load(filename, data); - } - - /** @override */ - unload() { - this.inkHost_.remove(); - this.inkHost_ = null; - } -} - -/** - * PDF plugin controller, responsible for communicating with the embedded plugin - * element. Dispatches a 'plugin-message' event containing the message from the - * plugin, if a message type not handled by this controller is received. - */ +// PDF plugin controller, responsible for communicating with the embedded plugin +// element. Dispatches a 'plugin-message' event containing the message from the +// plugin, if a message type not handled by this controller is received. export class PluginController extends ContentController { /** * @param {!HTMLEmbedElement} plugin @@ -407,11 +288,15 @@ export class PluginController extends ContentController { } /** @override */ - save(requireResult) { + save(requestType) { const resolver = new PromiseResolver(); const newToken = createToken(); this.pendingTokens_.set(newToken, resolver); - this.postMessage_({type: 'save', token: newToken, force: requireResult}); + this.postMessage_({ + type: 'save', + token: newToken, + saveRequestType: requestType, + }); return resolver.promise; } @@ -420,6 +305,7 @@ export class PluginController extends ContentController { const url = URL.createObjectURL(new Blob([data])); this.plugin_.removeAttribute('headers'); this.plugin_.setAttribute('stream-url', url); + this.plugin_.setAttribute('has-edits', ''); this.plugin_.style.display = 'block'; try { await this.getLoadedCallback_(); @@ -476,7 +362,6 @@ export class PluginController extends ContentController { /** * Handles the pdf file buffer received from the plugin. - * * @param {!SaveDataMessageData} messageData data of the message event. * @private */ diff --git a/chromium/chrome/browser/resources/pdf/elements/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/BUILD.gn index 1980c0a3421..0eaa9db89f2 100644 --- a/chromium/chrome/browser/resources/pdf/elements/BUILD.gn +++ b/chromium/chrome/browser/resources/pdf/elements/BUILD.gn @@ -14,6 +14,7 @@ js_type_check("closure_compile") { ":viewer-page-selector", ":viewer-password-screen", ":viewer-pdf-toolbar", + ":viewer-pdf-toolbar-new", ":viewer-toolbar-dropdown", ":viewer-zoom-button", ":viewer-zoom-toolbar", @@ -67,7 +68,10 @@ js_library("viewer-page-selector") { } js_library("viewer-password-screen") { - deps = [ "//ui/webui/resources/cr_elements/cr_input:cr_input.m" ] + deps = [ + "//ui/webui/resources/cr_elements/cr_input:cr_input.m", + "//ui/webui/resources/js:load_time_data.m", + ] } js_library("viewer-pdf-toolbar") { @@ -76,10 +80,21 @@ js_library("viewer-pdf-toolbar") { ":viewer-page-selector", ":viewer-toolbar-dropdown", "..:annotation_tool", + "..:constants", + "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:load_time_data.m", + "//ui/webui/resources/js:promise_resolver.m", ] externs_list = [ "$externs_path/pending.js" ] } +js_library("viewer-pdf-toolbar-new") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} + js_library("viewer-pen-options") { } @@ -109,6 +124,7 @@ html_to_js("web_components") { "viewer-page-selector.js", "viewer-password-screen.js", "viewer-pdf-toolbar.js", + "viewer-pdf-toolbar-new.js", "viewer-toolbar-dropdown.js", "viewer-zoom-button.js", "viewer-zoom-toolbar.js", diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.html b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.html index ec39a68550e..8cf60ea1aa7 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.html @@ -47,13 +47,13 @@ <paper-ripple></paper-ripple> <cr-icon-button id="expand" iron-icon="cr:chevron-right" on-click="toggleChildren_"></cr-icon-button> - <span id="title" tabindex="0">{{bookmark.title}}</span> + <span id="title" tabindex="0">[[bookmark.title]]</span> </div> <!-- dom-if will stamp the complex bookmark tree lazily as individual nodes are opened. --> <template is="dom-if" if="[[childrenShown_]]"> <template is="dom-repeat" items="[[bookmark.children]]"> - <viewer-bookmark bookmark="{{item}}" depth="[[childDepth_]]"> + <viewer-bookmark bookmark="[[item]]" depth="[[childDepth_]]"> </viewer-bookmark> </template> </template> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.html b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.html index 03047141d77..e2c210fbd08 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.html @@ -1,10 +1,10 @@ <style include="cr-hidden-style"></style> <cr-dialog id="dialog" no-cancel> - <div slot="title">[[strings.errorDialogTitle]]</div> - <div slot="body">[[strings.pageLoadFailed]]</div> + <div slot="title">$i18n{errorDialogTitle}</div> + <div slot="body">$i18n{pageLoadFailed}</div> <div slot="button-container" hidden$="[[!reloadFn]]"> <cr-button class="action-button" on-click="reload"> - [[strings.pageReload]] + $i18n{pageReload} </cr-button> </div> </cr-dialog> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js index d3383b06e25..d5702f659d4 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js @@ -15,8 +15,6 @@ Polymer({ properties: { reloadFn: Function, - - strings: Object, }, show() { diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.html b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.html index 1906119a962..61293db59aa 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.html @@ -1,13 +1,13 @@ <style include="cr-hidden-style"></style> <cr-dialog id="dialog" no-cancel> - <div slot="title">[[strings.annotationFormWarningTitle]]</div> - <div slot="body">[[strings.annotationFormWarningDetail]]</div> + <div slot="title">$i18n{annotationFormWarningTitle}</div> + <div slot="body">$i18n{annotationFormWarningDetail}</div> <div slot="button-container"> <cr-button class="cancel-button" on-click="onCancel"> - [[strings.annotationFormWarningKeepEditing]] + $i18n{annotationFormWarningKeepEditing} </cr-button> <cr-button class="action-button" on-click="onAction"> - [[strings.annotationFormWarningDiscard]] + $i18n{annotationFormWarningDiscard} </cr-button> </div> </cr-dialog> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js index d0cbd6d1de8..900c8d45b1e 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js @@ -14,10 +14,6 @@ Polymer({ _template: html`{__html_template__}`, - properties: { - strings: Object, - }, - /** @private {PromiseResolver} */ resolver_: null, diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js b/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js index fa208811e90..6c8b184407f 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js @@ -3,8 +3,9 @@ // found in the LICENSE file. import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + import {PDFMetrics} from '../metrics.js'; -import {Viewport} from '../viewport.js'; +import {PAGE_SHADOW, Viewport} from '../viewport.js'; /** @enum {string} */ const State = { @@ -62,7 +63,6 @@ Polymer({ /** * Whether we should suppress pointer events due to a gesture, * eg. pinch-zoom. - * * @private {boolean} */ pointerGesture_: false, @@ -96,19 +96,10 @@ Polymer({ /** * Dispatches a pointer event to Ink. - * * @param {PointerEvent} e */ dispatchPointerEvent_(e) { - // TODO(dstockwell) come up with a solution to propagate e.timeStamp. - this.ink_.dispatchPointerEvent(e.type, { - pointerId: e.pointerId, - pointerType: e.pointerType, - clientX: e.clientX, - clientY: e.clientY, - pressure: e.pressure, - buttons: e.buttons, - }); + this.ink_.dispatchPointerEvent(e); }, /** @param {TouchEvent} e */ @@ -135,10 +126,10 @@ Polymer({ // A multi-touch gesture has started with the active pointer. Cancel // the active pointer and suppress further events until it is released. this.pointerGesture_ = true; - this.ink_.dispatchPointerEvent('pointercancel', { + this.ink_.dispatchPointerEvent(new PointerEvent('pointercancel', { pointerId: this.activePointer_.pointerId, pointerType: this.activePointer_.pointerType, - }); + })); } return; } @@ -241,7 +232,7 @@ Polymer({ // color. await new Promise(resolve => setTimeout(resolve)); this.ink_.setOutOfBoundsColor(BACKGROUND_COLOR); - const spacing = Viewport.PAGE_SHADOW.top + Viewport.PAGE_SHADOW.bottom; + const spacing = PAGE_SHADOW.top + PAGE_SHADOW.bottom; this.ink_.setPageSpacing(spacing); this.style.visibility = 'visible'; }, @@ -256,8 +247,8 @@ Polymer({ const zoom = viewport.getZoom(); const documentWidth = viewport.getDocumentDimensions().width * zoom; // Adjust for page shadows. - const y = pos.y - Viewport.PAGE_SHADOW.top * zoom; - let x = pos.x - Viewport.PAGE_SHADOW.left * zoom; + const y = pos.y - PAGE_SHADOW.top * zoom; + let x = pos.x - PAGE_SHADOW.left * zoom; // Center the document if the width is smaller than the viewport. if (documentWidth < size.width) { x += (documentWidth - size.width) / 2; diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.html b/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.html index 966a10c3661..5504e761500 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.html @@ -34,5 +34,5 @@ width: 0; } </style> - <div id="text">{{label}}</div> + <div id="text">[[label]]</div> <div id="triangle-end"></div> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.html b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.html index 1402b838971..002a23ad3fc 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.html @@ -3,6 +3,8 @@ color: #fff; display: flex; font-size: 0.81rem; + + --page-selector-spacing: 4px; } :host ::selection { @@ -11,12 +13,10 @@ #pageselector::part(input), #pagelength { - box-sizing: content-box; - padding: 0 3px; /* --page-length-digits is set through JavaScript. 1px is added because * the unit 'ch' does not provide exact whole number pixels, and * therefore seems to have 1px-off bugginess. */ - width: calc(var(--page-length-digits) * 1ch + 1px); + width: calc(max(2, var(--page-length-digits)) * 1ch + 1px); } #pageselector { @@ -29,13 +29,18 @@ #pageselector::part(input) { background: rgba(0, 0, 0, 0.5); + box-sizing: content-box; caret-color: var(--cr-input-color); - text-align: end; + padding: 0 var(--page-selector-spacing); + } + + #divider { + margin: 0 var(--page-selector-spacing); } </style> <cr-input id="pageselector" value="[[pageNo]]" on-mouseup="select" on-value-changed="onInputValueChange_" on-change="pageNoCommitted" - aria-label$="{{strings.labelPageNumber}}"> + aria-label$="$i18n{labelPageNumber}"> </cr-input> - / - <span id="pagelength">{{docLength}}</span> + <span id="divider">/</span> + <span id="pagelength">[[docLength]]</span> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js index 5eda31ee514..6b8b55ad3dc 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js @@ -26,8 +26,6 @@ Polymer({ type: Number, value: 1, }, - - strings: Object, }, /** @return {!CrInputElement} */ diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.html b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.html index 43c0249bffa..b61cdb5434a 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.html @@ -4,20 +4,19 @@ } </style> <cr-dialog id="dialog" no-cancel> - <div slot="title">[[strings.passwordDialogTitle]]</div> + <div slot="title">$i18n{passwordDialogTitle}</div> <div slot="body"> - <div id="message">[[strings.passwordPrompt]]</div> + <div id="message">$i18n{passwordPrompt}</div> <cr-input id="password" type="password" - error-message="[[getErrorMessage_(strings.passwordInvalid, - invalid)]]" + error-message="[[getErrorMessage_(invalid)]]" invalid="[[invalid]]" autofocus> </cr-input> </div> <div slot="button-container"> <cr-button id="submit" class="action-button" on-click="submit"> - [[strings.passwordSubmit]] + $i18n{passwordSubmit} </cr-button> </div> </cr-dialog> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js index 79cd849c56b..7bc4507d700 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js @@ -8,6 +8,7 @@ import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; Polymer({ @@ -17,8 +18,6 @@ Polymer({ properties: { invalid: Boolean, - - strings: Object, }, get active() { @@ -57,10 +56,9 @@ Polymer({ * Returns |message| if input is invalid, otherwise empty string. * This avoids setting the error message (which announces to screen readers) * when there is no error. - * @param {string} message * @return {string} */ - getErrorMessage_(message) { - return this.invalid ? message : ''; + getErrorMessage_() { + return this.invalid ? loadTimeData.getString('passwordInvalid') : ''; } }); diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html new file mode 100644 index 00000000000..075635defbb --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html @@ -0,0 +1,10 @@ +<style> + :host { + --pdf-toolbar-background-color: rgb(50, 54, 57); + background-color: var(--pdf-toolbar-background-color); + box-shadow: var(--cr-elevation-2); + color: white; + height: 48px; + } +</style> +New PDF Viewer toolbar will appear here. diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js new file mode 100644 index 00000000000..06e1d118df0 --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js @@ -0,0 +1,17 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +class ViewerPdfToolbarNewElement extends PolymerElement { + static get is() { + return 'viewer-pdf-toolbar-new'; + } + + static get template() { + return html`{__html_template__}`; + } +} +customElements.define( + ViewerPdfToolbarNewElement.is, ViewerPdfToolbarNewElement); diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html index 6a8daca8ea7..51c7bc66cb5 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html @@ -1,4 +1,9 @@ <style include="cr-hidden-style"> + :host { + --pdf-toolbar-background-color: rgb(50, 54, 57); + --pdf-toolbar-text-color: rgb(241, 241, 241); + } + :host ::selection { background: rgba(255, 255, 255, 0.3); } @@ -36,7 +41,7 @@ } cr-icon-button { - --cr-icon-button-fill-color: rgb(241, 241, 241); + --cr-icon-button-fill-color: var(--pdf-toolbar-text-color); margin: 6px; } @@ -54,8 +59,8 @@ } #toolbar { - @apply --shadow-elevation-2dp; - background-color: rgb(50, 54, 57); + background-color: var(--pdf-toolbar-background-color); + box-shadow: var(--cr-elevation-2); position: relative; } @@ -67,7 +72,7 @@ #toolbar, #annotations-bar { - color: rgb(241, 241, 241); + color: var(--pdf-toolbar-text-color); display: flex; height: 48px; padding: 0 16px; @@ -90,7 +95,7 @@ #pen, #highlighter { - --dropdown-open-background: rgb(50, 54, 57); + --dropdown-open-background: var(--pdf-viewer-background-color); } #eraser { @@ -138,10 +143,6 @@ #rotate-left { display: none; } - - #pageselector-container { - flex: 2; - } } @media(max-width: 450px) { @@ -156,40 +157,55 @@ display: none; } } + + cr-action-menu::part(dialog) { + position: fixed; + top: 48px; + } </style> <div id="toolbar"> <div id="aligner"> - <span id="title" title="{{docTitle}}"> - <span>{{docTitle}}</span> + <span id="title" title="[[docTitle]]"> + <span>[[docTitle]]</span> </span> <div id="pageselector-container"> <viewer-page-selector id="pageselector" class="invisible" - doc-length="{{docLength}}" page-no="{{pageNo}}" - strings="{{strings}}"> + doc-length="[[docLength]]" page-no="[[pageNo]]"> </viewer-page-selector> </div> <div id="buttons" class="invisible"> - <template is="dom-if" if="[[pdfAnnotationsEnabled]]"> +<if expr="chromeos"> + <template is="dom-if" if="[[pdfAnnotationsEnabled_]]"> <cr-icon-button id="annotate" iron-icon="pdf:create" disabled="[[!annotationAvailable]]" on-click="toggleAnnotation" - aria-label$="{{strings.tooltipAnnotate}}" - title$="{{strings.tooltipAnnotate}}"></cr-icon-button> + aria-label$="$i18n{tooltipAnnotate}" + title="$i18n{tooltipAnnotate}"></cr-icon-button> </template> +</if> <cr-icon-button id="rotate-right" iron-icon="pdf:rotate-right" disabled="[[annotationMode]]" on-click="rotateRight" - aria-label$="{{strings.tooltipRotateCW}}" - title$="{{strings.tooltipRotateCW}}"></cr-icon-button> + aria-label$="$i18n{tooltipRotateCW}" + title="$i18n{tooltipRotateCW}"></cr-icon-button> <cr-icon-button id="download" iron-icon="cr:file-download" - on-click="download" aria-label$="{{strings.tooltipDownload}}" - title$="{{strings.tooltipDownload}}"></cr-icon-button> + on-click="onDownloadClick_" aria-label$="$i18n{tooltipDownload}" + aria-haspopup$="[[downloadHasPopup_]]" + title="$i18n{tooltipDownload}"></cr-icon-button> + <cr-action-menu id="downloadMenu"> + <button class="dropdown-item" on-click="onDownloadEditedClick_"> + $i18n{downloadEdited} + </button> + <button class="dropdown-item" on-click="onDownloadOriginalClick_"> + $i18n{downloadOriginal} + </button> + </cr-action-menu> <cr-icon-button id="print" iron-icon="cr:print" on-click="print" - hidden="[[!printingEnabled]]" title$="{{strings.tooltipPrint}}" - aria-label$="{{strings.tooltipPrint}}"></cr-icon-button> + hidden="[[!printingEnabled_]]" title="$i18n{tooltipPrint}" + aria-label$="$i18n{tooltipPrint}"></cr-icon-button> <viewer-toolbar-dropdown id="bookmarks" selected @@ -197,7 +213,7 @@ hidden$="[[!bookmarks.length]]" open-icon="pdf:bookmark" closed-icon="pdf:bookmark-border" - header="{{strings.bookmarks}}"> + header="$i18n{bookmarks}"> <template is="dom-repeat" items="[[bookmarks]]"> <viewer-bookmark bookmark="[[item]]" depth="0"></viewer-bookmark> </template> @@ -211,6 +227,7 @@ </div> </div> +<if expr="chromeos"> <div id="annotations-bar" hidden> <viewer-toolbar-dropdown id="pen" selected$="[[isAnnotationTool_('pen', annotationTool.tool)]]" @@ -220,7 +237,7 @@ closed-icon="pdf:marker" dropdown-centered hide-header - header$="{{strings.annotationPen}}" + header="$i18n{annotationPen}" style="--pen-tip-fill: #000000"> <viewer-pen-options selected-color="#000000" @@ -239,7 +256,7 @@ closed-icon="pdf:highlighter" dropdown-centered hide-header - header$="{{strings.annotationHighlighter}}" + header="$i18n{annotationHighlighter}" style="--pen-tip-fill: #ffbc00"> <viewer-pen-options selected-color="#ffbc00" @@ -253,18 +270,19 @@ <cr-icon-button id="eraser" selected$="[[isAnnotationTool_('eraser', annotationTool.tool)]]" on-click="annotationToolClicked_" iron-icon="pdf:eraser" - aria-label$="{{strings.annotationEraser}}" - title$="{{strings.annotationEraser}}"></cr-icon-button> + aria-label$="$i18n{annotationEraser}" + title="$i18n{annotationEraser}"></cr-icon-button> <div id="annotation-separator"></div> <cr-icon-button id="undo" disabled="[[!canUndoAnnotation]]" iron-icon="pdf:undo" on-click="undo" - aria-label$="{{strings.annotationUndo}}" - title$="{{strings.annotationUndo}}"></cr-icon-button> + aria-label$="$i18n{annotationUndo}" + title="$i18n{annotationUndo}"></cr-icon-button> <cr-icon-button id="redo" disabled="[[!canRedoAnnotation]]" iron-icon="pdf:redo" on-click="redo" - aria-label$="{{strings.annotationRedo}}" - title$="{{strings.annotationRedo}}"></cr-icon-button> + aria-label$="$i18n{annotationRedo}" + title="$i18n{annotationRedo}"></cr-icon-button> </div> +</if> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js index 9fb821a0ac4..defc20f57bb 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js @@ -10,13 +10,19 @@ import './icons.js'; import './viewer-bookmark.js'; import './viewer-page-selector.js'; import './viewer-toolbar-dropdown.js'; - // <if expr="chromeos"> import './viewer-pen-options.js'; + // </if> +import {AnchorAlignment} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.m.js'; +import {assert} from 'chrome://resources/js/assert.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + import {Bookmark} from '../bookmark_type.js'; +import {SaveRequestType} from '../constants.js'; Polymer({ is: 'viewer-pdf-toolbar', @@ -29,10 +35,7 @@ Polymer({ * example the PDF is encrypted or password protected. Note, this is * true regardless of whether the feature flag is enabled. */ - annotationAvailable: { - type: Boolean, - value: true, - }, + annotationAvailable: Boolean, /** Whether the viewer is currently in annotation mode. */ annotationMode: { @@ -45,7 +48,6 @@ Polymer({ /** @type {?AnnotationTool} */ annotationTool: { type: Object, - value: null, notify: true, }, @@ -74,6 +76,15 @@ Polymer({ /** The title of the PDF document. */ docTitle: String, + hasEdits: Boolean, + + hasEnteredAnnotationMode: Boolean, + + isFormFieldFocused: { + type: Boolean, + observer: 'onFormFieldFocusedChanged_', + }, + /** The current loading progress of the PDF document (0 - 100). */ loadProgress: { type: Number, @@ -89,24 +100,52 @@ Polymer({ /** The number of the page being viewed (1-based). */ pageNo: Number, - /** Whether the PDF Annotations feature is enabled. */ - pdfAnnotationsEnabled: { + /** + * Whether the PDF Annotations feature is enabled. + * @private + */ + pdfAnnotationsEnabled_: { type: Boolean, value: false, }, - /** Whether the Printing feature is enabled. */ - printingEnabled: { + /** + * Whether the Printing feature is enabled. + * @private + */ + printingEnabled_: { type: Boolean, value: false, }, - strings: Object, + /** @private */ + downloadHasPopup_: { + type: String, + computed: 'computeDownloadHasPopup_(' + + 'pdfFormSaveEnabled_, hasEdits, hasEnteredAnnotationMode)', + }, + + strings: { + type: Object, + observer: 'onStringsSet_', + }, + + /** + * Whether the PDF Form save feature is enabled. + * @private + */ + pdfFormSaveEnabled_: { + type: Boolean, + value: false, + }, }, /** @type {?Object} */ animation_: null, + /** @private {?PromiseResolver<boolean>} */ + waitForFormFocusChange_: null, + /** * @param {number} newProgress * @param {number} oldProgress @@ -119,7 +158,9 @@ Polymer({ this.$.pageselector.classList.toggle('invisible', !loaded); this.$.buttons.classList.toggle('invisible', !loaded); this.$.progress.style.opacity = loaded ? 0 : 1; + // <if expr="chromeos"> this.$['annotations-bar'].hidden = !loaded || !this.annotationMode; + // </if> } }, @@ -168,7 +209,8 @@ Polymer({ /** @return {boolean} Whether the toolbar should be kept open. */ shouldKeepOpen() { return this.$.bookmarks.dropdownOpen || this.loadProgress < 100 || - this.$.pageselector.isActive() || this.annotationMode; + this.$.pageselector.isActive() || this.annotationMode || + this.$.downloadMenu.open; }, /** @return {boolean} Whether a dropdown was open and was hidden. */ @@ -178,6 +220,7 @@ Polymer({ this.$.bookmarks.toggleDropdown(); result = true; } + // <if expr="chromeos"> if (this.$.pen.dropdownOpen) { this.$.pen.toggleDropdown(); result = true; @@ -186,6 +229,7 @@ Polymer({ this.$.highlighter.toggleDropdown(); result = true; } + // </if> return result; }, @@ -198,8 +242,67 @@ Polymer({ this.fire('rotate-right'); }, - download() { - this.fire('save'); + /** @private */ + showDownloadMenu_() { + this.$.downloadMenu.showAt(this.$.download, { + anchorAlignmentX: AnchorAlignment.CENTER, + anchorAlignmentY: AnchorAlignment.AFTER_END, + noOffset: true, + }); + // For tests + this.fire('download-menu-shown-for-testing'); + }, + + /** @private */ + onDownloadClick_() { + this.waitForEdits_().then(hasEdits => { + if (hasEdits) { + this.showDownloadMenu_(); + } else { + this.fire('save', SaveRequestType.ORIGINAL); + } + }); + }, + + /** + * @return {!Promise<boolean>} Promise that resolves with true if the PDF has + * edits and/or annotations, and false otherwise. + * @private + */ + waitForEdits_() { + if (this.hasEditsToSave_()) { + return Promise.resolve(true); + } + if (!this.isFormFieldFocused || !this.pdfFormSaveEnabled_) { + return Promise.resolve(false); + } + this.waitForFormFocusChange_ = new PromiseResolver(); + return this.waitForFormFocusChange_.promise; + }, + + /** @private */ + onFormFieldFocusedChanged_() { + if (!this.waitForFormFocusChange_) { + return; + } + + this.waitForFormFocusChange_.resolve(this.hasEdits); + this.waitForFormFocusChange_ = null; + }, + + /** @private */ + onDownloadOriginalClick_() { + this.fire('save', SaveRequestType.ORIGINAL); + this.$.downloadMenu.close(); + }, + + /** @private */ + onDownloadEditedClick_() { + this.fire( + 'save', + this.hasEnteredAnnotationMode ? SaveRequestType.ANNOTATION : + SaveRequestType.EDITED); + this.$.downloadMenu.close(); }, print() { @@ -255,7 +358,7 @@ Polymer({ const tool = element.id; const options = element.querySelector('viewer-pen-options') || { selectedSize: 1, - selectedColor: null, + selectedColor: undefined, }; const attributeStyleMap = element.attributeStyleMap; attributeStyleMap.set('--pen-tip-fill', options.selectedColor); @@ -278,4 +381,32 @@ Polymer({ isAnnotationTool_(toolName) { return !!this.annotationTool && this.annotationTool.tool === toolName; }, + + /** + * @return {boolean} + * @private + */ + hasEditsToSave_() { + return this.hasEnteredAnnotationMode || + (this.pdfFormSaveEnabled_ && this.hasEdits); + }, + + /** + * @return {string} The value for the aria-haspopup attribute for the download + * button. + * @private + */ + computeDownloadHasPopup_() { + return this.hasEditsToSave_() ? 'menu' : 'false'; + }, + + /** @private */ + onStringsSet_() { + assert(this.strings); + + this.pdfAnnotationsEnabled_ = + loadTimeData.getBoolean('pdfAnnotationsEnabled'); + this.pdfFormSaveEnabled_ = loadTimeData.getBoolean('pdfFormSaveEnabled'); + this.printingEnabled_ = loadTimeData.getBoolean('printingEnabled'); + }, }); diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.html b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.html index b44bf89f9c9..e98c1c20513 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.html @@ -65,8 +65,8 @@ on-pointerdown="blurOnPointerDown"> </template> <cr-icon-button id="expand" iron-icon="cr:expand-more" tabindex="3" - on-click="toggleExpanded_" aria-label$="[[strings.annotationExpand]]" - title$="[[strings.annotationExpand]]"></cr-icon-button> + on-click="toggleExpanded_" aria-label$="$i18n{annotationExpand}" + title$="$i18n{annotationExpand}"></cr-icon-button> </div> <div id="separator"></div> <div id="sizes" on-change="sizeChanged_"> @@ -74,7 +74,7 @@ <input type="radio" name="size" value="[[item.size]]" checked$="[[equal_(selectedSize, item.size)]]" tabindex="2" style="--item-size: [[item.size]]" - title$="{{lookup_(strings, item.name)}}" + title="[[lookup_(strings, item.name)]]" aria-label$="[[lookup_(strings, item.name)]]" on-pointerdown="blurOnPointerDown"> </template> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js index 0cc12c94384..fd7e6e8661d 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js @@ -52,50 +52,62 @@ const sizes = [ {name: 'annotationSize20', size: 1}, ]; -/** - * Displays a set of radio buttons to select from - * a predefined list of colors and sizes. - */ +// Displays a set of radio buttons to select from a predefined list of colors +// and sizes. Polymer({ is: 'viewer-pen-options', _template: html`{__html_template__}`, properties: { + /** @private */ expanded_: { type: Boolean, value: false, }, + selectedSize: { type: Number, value: 0.250, notify: true, }, + selectedColor: { type: String, value: '#000000', notify: true, }, + + /** @private */ sizes_: { type: Array, value: sizes, }, + + /** @private */ colors_: { type: Array, value: colors, }, + strings: Object, }, - /** @type {Array<!Animation>} */ + /** @private {Array<!Animation>} */ expandAnimations_: null, - /** @param {Event} e */ + /** + * @param {!Event} e + * @private + */ sizeChanged_(e) { this.selectedSize = Number(e.target.value); }, - /** @param {Event} e */ + /** + * @param {!Event} e + * @private + */ colorChanged_(e) { this.selectedColor = e.target.value; }, @@ -125,6 +137,7 @@ Polymer({ /** * Updates the state of the UI to reflect the current value of `expanded`. * Starts or reverses animations and enables/disable controls. + * @private */ updateExpandedState_() { const colors = this.$.colors; @@ -176,19 +189,16 @@ Polymer({ animation.play(); } for (const input of colors.querySelectorAll('input:nth-child(n+8)')) { - if (this.expanded_) { - input.removeAttribute('disabled'); - } else { - input.setAttribute('disabled', ''); - } + input.toggleAttribute('disabled', !this.expanded_); } }, /** * Used to determine equality in computed bindings. - * * @param {*} a * @param {*} b + * @return {boolean} Whether a === b + * @private */ equal_(a, b) { return a === b; @@ -196,10 +206,10 @@ Polymer({ /** * Used to lookup a string in a computed binding. - * * @param {Object} strings * @param {string} name * @return {string} + * @private */ lookup_(strings, name) { return strings ? strings[name] : ''; @@ -209,6 +219,7 @@ Polymer({ * Used to remove focus when clicking or tapping on a styled input * element. This is a workaround until we can use the :focus-visible * pseudo selector. + * @param {!Event} e */ blurOnPointerDown(e) { const target = e.target; diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.html b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.html index 8c6e7640bde..ff49695f629 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.html @@ -27,23 +27,17 @@ #dropdown { background-color: var(--cr-menu-background-color); border-radius: 4px; + box-shadow: var(--cr-menu-shadow); color: var(--cr-primary-text-color); overflow-y: hidden; padding-bottom: 2px; width: var(--dropdown-width); } - @media (prefers-color-scheme: light) { - #dropdown { - @apply --shadow-elevation-2dp; - } - } - @media (prefers-color-scheme: dark) { #dropdown { background-image: linear-gradient(var(--cr-menu-background-sheen), var(--cr-menu-background-sheen)); - box-shadow: var(--cr-menu-shadow); } } @@ -89,7 +83,7 @@ <div id="container"> <div id="dropdown" style="display: none"> <template is="dom-if" if="[[!hideHeader]]"> - <h1>{{header}}</h1> + <h1>[[header]]</h1> </template> <div id="scroll-container"> <slot></slot> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html index f51075c5cab..ad97fce8a23 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html @@ -35,11 +35,10 @@ --cr-icon-button-fill-color: var(--paper-grey-700); --cr-icon-button-icon-size: 20px; --cr-icon-button-size: 36px; - --cr-icon-button-fill-color-focus: rgb(242, 242, 242); background-color: rgb(242, 242, 242); border-radius: 50%; + box-shadow: var(--cr-elevation-1); overflow: visible; - @apply --shadow-elevation-2dp; } cr-icon-button([disabled]) { @@ -48,7 +47,6 @@ :host-context([is-print-preview]) cr-icon-button { --cr-icon-button-fill-color: white; - --cr-icon-button-fill-color-focus: var(--google-grey-600); --cr-icon-button-size: 32px; background-color: var(--google-grey-600); } @@ -62,17 +60,16 @@ @media (prefers-color-scheme: dark) { :host-context([is-print-preview]) cr-icon-button { --cr-icon-button-fill-color: var(--google-grey-200); - --cr-icon-button-fill-color-focus: var(--google-grey-900); background-color: var(--google-grey-900); } } :host([keyboard-navigation-active]) cr-icon-button:focus { - @apply --shadow-elevation-6dp; + box-shadow: var(--cr-elevation-4); } cr-icon-button:active { - @apply --shadow-elevation-8dp; + box-shadow: var(--cr-elevation-5); } </style> <div id="wrapper"> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html index ab6a4d461ca..341f6bbf4c7 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html @@ -67,7 +67,7 @@ <!-- TODO(crbug.com/51472): Change icons for two-up-view-button --> <!-- once they are finalized. --> <viewer-zoom-button id="two-up-view-button" delay="100" - disabled="[[annotationMode]]" hidden$="[[!twoUpViewEnabled]]" + disabled="[[annotationMode]]" hidden$="[[!twoUpViewEnabled_]]" on-fabclick="twoUpViewToggle_" keyboard-navigation-active="[[keyboardNavigationActive_]]" icons="pdf:create pdf:eraser"></viewer-zoom-button> diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js index d58712f7562..f3bab8c69e1 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js @@ -8,7 +8,9 @@ import './icons.js'; import './viewer-zoom-button.js'; import {assert} from 'chrome://resources/js/assert.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + import {FittingType, TwoUpViewAction} from '../constants.js'; /** @@ -32,19 +34,25 @@ Polymer({ properties: { /** Whether the viewer is currently in annotation mode. */ - annotationMode: { + annotationMode: Boolean, + + isPrintPreview: { type: Boolean, value: false, }, - isPrintPreview: Boolean, + strings: { + type: Object, + observer: 'onStringsSet_', + }, - twoUpViewEnabled: Boolean, + /** @private */ + twoUpViewEnabled_: Boolean, /** @private */ fitButtonDelay_: { type: Number, - computed: 'computeFitButtonDelay_(twoUpViewEnabled)', + computed: 'computeFitButtonDelay_(twoUpViewEnabled_)', }, /** @private */ @@ -55,12 +63,11 @@ Polymer({ }, /** - * @param {boolean} twoUpViewEnabled Whether two-up view button is enabled. - * @return {number} Delay for :qthe fit button. + * @return {number} Delay for the fit button. * @private */ - computeFitButtonDelay_(twoUpViewEnabled) { - return twoUpViewEnabled ? 150 : 100; + computeFitButtonDelay_() { + return this.twoUpViewEnabled_ ? 150 : 100; }, listeners: { @@ -106,20 +113,27 @@ Polymer({ /** * Change button tooltips to match any changes to localized strings. - * @param {!{tooltipFitToPage: string, - * tooltipFitToWidth: string, - * tooltipTwoUpViewEnable: string, - * tooltipTwoUpViewDisable: string, - * tooltipZoomIn: string, - * tooltipZoomOut: string}} strings + * @private */ - setStrings(strings) { + onStringsSet_() { + const strings = + /** + * @type {{tooltipFitToPage: string, + * tooltipFitToWidth: string, + * tooltipTwoUpViewEnable: string, + * tooltipTwoUpViewDisable: string, + * tooltipZoomIn: string, + * tooltipZoomOut: string}} + */ + (this.strings); this.$['fit-button'].tooltips = [strings.tooltipFitToPage, strings.tooltipFitToWidth]; this.$['two-up-view-button'].tooltips = [strings.tooltipTwoUpViewEnable, strings.tooltipTwoUpViewDisable]; this.$['zoom-in-button'].tooltips = [strings.tooltipZoomIn]; this.$['zoom-out-button'].tooltips = [strings.tooltipZoomOut]; + this.twoUpViewEnabled_ = + loadTimeData.getBoolean('pdfTwoUpViewEnabled') && !this.isPrintPreview; }, /** Handle clicks of the fit-button. */ @@ -175,7 +189,7 @@ Polymer({ * @private */ twoUpViewToggle_: function() { - assert(this.twoUpViewEnabled); + assert(this.twoUpViewEnabled_); const twoUpViewAction = this.$['two-up-view-button'].activeIndex === TWO_UP_VIEW_DISABLED_STATE ? TwoUpViewAction.TWO_UP_VIEW_ENABLE : @@ -184,16 +198,12 @@ Polymer({ this.fire('two-up-view-changed', twoUpViewAction); }, - /** - * Handle clicks of the zoom-in-button. - */ + /** Handle clicks of the zoom-in-button. */ zoomIn() { this.fire('zoom-in'); }, - /** - * Handle clicks of the zoom-out-button. - */ + /** Handle clicks of the zoom-out-button. */ zoomOut() { this.fire('zoom-out'); }, diff --git a/chromium/chrome/browser/resources/pdf/gesture_detector.js b/chromium/chrome/browser/resources/pdf/gesture_detector.js index e8a0db4e6a3..6755d76b9b0 100644 --- a/chromium/chrome/browser/resources/pdf/gesture_detector.js +++ b/chromium/chrome/browser/resources/pdf/gesture_detector.js @@ -2,34 +2,43 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'; + /** - * A class that listens for touch events and produces events when these - * touches form gestures (e.g. pinching). + * @typedef {{ + * center: !{x: number, y: number}, + * direction: (string|undefined), + * scaleRatio: (?number|undefined), + * startScaleRatio: (?number|undefined), + * }} */ +export let PinchEventDetail; + +// A class that listens for touch events and produces events when these +// touches form gestures (e.g. pinching). export class GestureDetector { /** - * @param {!Element} element The element to monitor for touch gestures. + * @param {!EventTarget|!Element} element The element to monitor for touch + * gestures. */ constructor(element) { - /** @private {!Element} */ - this.element_ = element; - - this.element_.addEventListener( + element.addEventListener( 'touchstart', /** @type {function(!Event)} */ (this.onTouchStart_.bind(this)), {passive: true}); const boundOnTouch = /** @type {function(!Event)} */ (this.onTouch_.bind(this)); - this.element_.addEventListener('touchmove', boundOnTouch, {passive: true}); - this.element_.addEventListener('touchend', boundOnTouch, {passive: true}); - this.element_.addEventListener( - 'touchcancel', boundOnTouch, {passive: true}); + element.addEventListener('touchmove', boundOnTouch, {passive: true}); + element.addEventListener('touchend', boundOnTouch, {passive: true}); + element.addEventListener('touchcancel', boundOnTouch, {passive: true}); - this.element_.addEventListener( + element.addEventListener( 'wheel', /** @type {function(!Event)} */ (this.onWheel_.bind(this)), {passive: false}); + document.addEventListener( + 'contextmenu', e => this.handleContextMenuEvent_(e)); this.pinchStartEvent_ = null; this.lastTouchTouchesCount_ = 0; @@ -52,24 +61,17 @@ export class GestureDetector { */ this.wheelEndTimeout_ = null; - /** @private {!Map<string, !Array<!Function>>} */ - this.listeners_ = - new Map([['pinchstart', []], ['pinchupdate', []], ['pinchend', []]]); + /** @private {!EventTarget} */ + this.eventTarget_ = new EventTarget(); } - /** - * Add a |listener| to be notified of |type| events. - * - * @param {string} type The event type to be notified for. - * @param {!Function} listener The callback. - */ - addEventListener(type, listener) { - if (this.listeners_.has(type)) { - this.listeners_.get(type).push(listener); - } + /** @return {!EventTarget} */ + getEventTarget() { + return this.eventTarget_; } /** + * Public for tests. * @return {boolean} True if the last touch start was a two finger touch. */ wasTwoFingerTouch() { @@ -77,22 +79,17 @@ export class GestureDetector { } /** - * Call the relevant listeners with the given |pinchEvent|. - * - * @param {!Object} pinchEvent The event to notify the listeners of. + * Call the relevant listeners with the given |PinchEventDetail|. + * @param {string} type The type of pinch event. + * @param {!PinchEventDetail} detail The event to notify the listeners of. * @private */ - notify_(pinchEvent) { - const listeners = this.listeners_.get(pinchEvent.type); - - for (const l of listeners) { - l(pinchEvent); - } + notify_(type, detail) { + this.eventTarget_.dispatchEvent(new CustomEvent(type, {detail})); } /** * The callback for touchstart events on the element. - * * @param {!TouchEvent} event Touch event on the element. * @private */ @@ -104,12 +101,11 @@ export class GestureDetector { this.pinchStartEvent_ = event; this.lastEvent_ = event; - this.notify_({type: 'pinchstart', center: GestureDetector.center_(event)}); + this.notify_('pinchstart', {center: GestureDetector.center_(event)}); } /** * The callback for touch move, end, and cancel events on the element. - * * @param {!TouchEvent} event Touch event on the element. * @private */ @@ -126,14 +122,12 @@ export class GestureDetector { const startScaleRatio = GestureDetector.pinchScaleRatio_(lastEvent, this.pinchStartEvent_); const center = GestureDetector.center_(lastEvent); - const endEvent = { - type: 'pinchend', - startScaleRatio: startScaleRatio, - center: center - }; this.pinchStartEvent_ = null; this.lastEvent_ = null; - this.notify_(endEvent); + this.notify_('pinchend', { + startScaleRatio: startScaleRatio, + center: center, + }); return; } @@ -141,12 +135,11 @@ export class GestureDetector { const startScaleRatio = GestureDetector.pinchScaleRatio_(event, this.pinchStartEvent_); const center = GestureDetector.center_(event); - this.notify_({ - type: 'pinchupdate', + this.notify_('pinchupdate', { scaleRatio: scaleRatio, direction: scaleRatio > 1.0 ? 'in' : 'out', startScaleRatio: startScaleRatio, - center: center + center: center, }); this.lastEvent_ = event; @@ -154,7 +147,6 @@ export class GestureDetector { /** * The callback for wheel events on the element. - * * @param {!WheelEvent} event Wheel event on the element. * @private */ @@ -179,16 +171,15 @@ export class GestureDetector { if (this.accumulatedWheelScale_ == null) { this.accumulatedWheelScale_ = 1.0; - this.notify_({type: 'pinchstart', center: position}); + this.notify_('pinchstart', {center: position}); } this.accumulatedWheelScale_ *= scale; - this.notify_({ - type: 'pinchupdate', + this.notify_('pinchupdate', { scaleRatio: scale, direction: scale > 1.0 ? 'in' : 'out', startScaleRatio: this.accumulatedWheelScale_, - center: position + center: position, }); // We don't get any phase information for the ctrl-wheels, so we don't know @@ -200,21 +191,35 @@ export class GestureDetector { } const gestureEndDelayMs = 100; const endEvent = { - type: 'pinchend', startScaleRatio: this.accumulatedWheelScale_, - center: position + center: position, }; - this.wheelEndTimeout_ = window.setTimeout(function(endEvent) { - this.notify_(endEvent); + this.wheelEndTimeout_ = window.setTimeout(() => { + this.notify_('pinchend', endEvent); this.wheelEndTimeout_ = null; this.accumulatedWheelScale_ = null; - }.bind(this), gestureEndDelayMs, endEvent); + }, gestureEndDelayMs); + } + + /** + * @param {!Event} e The context menu event + * @private + */ + handleContextMenuEvent_(e) { + // Stop Chrome from popping up the context menu on long press. We need to + // make sure the start event did not have 2 touches because we don't want + // to block two finger tap opening the context menu. We check for + // firesTouchEvents in order to not block the context menu on right click. + const capabilities = + /** @type {{ sourceCapabilities: Object }} */ (e).sourceCapabilities; + if (capabilities.firesTouchEvents && !this.wasTwoFingerTouch()) { + e.preventDefault(); + } } /** * Computes the change in scale between this touch event * and a previous one. - * * @param {!TouchEvent} event Latest touch event on the element. * @param {!TouchEvent} prevEvent A previous touch event on the element. * @return {?number} The ratio of the scale of this event and the @@ -229,7 +234,6 @@ export class GestureDetector { /** * Computes the distance between fingers. - * * @param {!TouchEvent} event Touch event with at least 2 touch points. * @return {number} Distance between touch[0] and touch[1]. * @private @@ -244,9 +248,8 @@ export class GestureDetector { /** * Computes the midpoint between fingers. - * * @param {!TouchEvent} event Touch event with at least 2 touch points. - * @return {!Object} Midpoint between touch[0] and touch[1]. + * @return {!{x: number, y: number}} Midpoint between touch[0] and touch[1]. * @private */ static center_(event) { diff --git a/chromium/chrome/browser/resources/pdf/index.css b/chromium/chrome/browser/resources/pdf/index.css index 1f6605930ec..20fd3b62cda 100644 --- a/chromium/chrome/browser/resources/pdf/index.css +++ b/chromium/chrome/browser/resources/pdf/index.css @@ -13,53 +13,3 @@ body { line-height: 154%; margin: 0; } - -viewer-page-indicator { - opacity: 0; - visibility: hidden; - z-index: 2; -} - -viewer-pdf-toolbar { - position: fixed; - width: 100%; - z-index: 4; -} - -#content { - height: 100%; - position: fixed; - width: 100%; - z-index: 1; -} - - -viewer-ink-host, -#plugin { - height: 100%; - position: absolute; - width: 100%; -} - -#sizer { - position: absolute; - z-index: 0; -} - -@media(max-height: 250px) { - viewer-pdf-toolbar { - display: none; - } -} - -@media(max-height: 200px) { - viewer-zoom-toolbar { - display: none; - } -} - -@media(max-width: 300px) { - viewer-zoom-toolbar { - display: none; - } -} diff --git a/chromium/chrome/browser/resources/pdf/index.html b/chromium/chrome/browser/resources/pdf/index.html index 6a78136126d..bce88410976 100644 --- a/chromium/chrome/browser/resources/pdf/index.html +++ b/chromium/chrome/browser/resources/pdf/index.html @@ -1,5 +1,6 @@ <!doctype html> -<html $i18n{a11yenhanced}> +<html dir="$i18n{textdirection}" lang="$i18n{language}" + $i18n{pdfViewerUpdateEnabledAttribute}> <head> <meta charset="utf-8"> @@ -7,22 +8,8 @@ <link rel="stylesheet" href="index.css"> </head> <body> - -<viewer-pdf-toolbar id="toolbar" hidden></viewer-pdf-toolbar> - -<div id="sizer"></div> -<viewer-password-screen id="password-screen"></viewer-password-screen> - -<viewer-zoom-toolbar id="zoom-toolbar" hidden></viewer-zoom-toolbar> - -<viewer-error-screen id="error-screen"></viewer-error-screen> - -<if expr="chromeos"> -<viewer-form-warning id="form-warning"></viewer-form-warning> -</if> - -<div id="content"></div> - +<pdf-viewer id="viewer"></pdf-viewer> </body> <script type="module" src="main.js"></script> +<script type="module" src="pdf_viewer.js"></script> </html> diff --git a/chromium/chrome/browser/resources/pdf/index_pp.html b/chromium/chrome/browser/resources/pdf/index_pp.html index 5c44ada5d73..fd18cd50280 100644 --- a/chromium/chrome/browser/resources/pdf/index_pp.html +++ b/chromium/chrome/browser/resources/pdf/index_pp.html @@ -1,5 +1,5 @@ <!doctype html> -<html $i18n{a11yenhanced}> +<html is-print-preview dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> @@ -7,16 +7,11 @@ <link rel="stylesheet" href="index.css"> </head> <body> - -<div id="sizer"></div> -<viewer-zoom-toolbar id="zoom-toolbar" hidden></viewer-zoom-toolbar> - -<viewer-page-indicator id="page-indicator"></viewer-page-indicator> - -<viewer-error-screen id="error-screen"></viewer-error-screen> - -<div id="content"></div> - +<pdf-viewer-pp id="viewer"></pdf-viewer-pp> </body> -<script type="module" src="main_pp.js"></script> +<script type="module" src="main.js"></script> +<!-- The line below refers to pdf_viewer_pp.js, which is served under the path + pdf_viewer.js so that the PDF viewer and Print Preview viewer can use the + same main.js source. main.js imports pdf_viewer.js. --> +<script type="module" src="pdf_viewer.js"></script> </html> diff --git a/chromium/chrome/browser/resources/pdf/ink/externs.js b/chromium/chrome/browser/resources/pdf/ink/externs.js deleted file mode 100644 index 8af66dfc91f..00000000000 --- a/chromium/chrome/browser/resources/pdf/ink/externs.js +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview We don't rely on any of these types but they are missing - * from the Ink extern file currently and need to be defined somewhere. - * @externs - */ - -var ink = {}; // eslint-disable-line no-var -ink.proto.scene_change = {}; - -/** @constructor */ -ink.proto.Snapshot = function() {}; - -/** @constructor */ -ink.proto.Command = function() {}; - -/** @constructor */ -ink.proto.MutationPacket = function() {}; - -/** @constructor */ -ink.proto.SetCallbackFlags = function() {}; - -/** @constructor */ -ink.proto.ToolEvent = function() {}; - -/** @constructor */ -ink.Box = function() {}; - -/** @constructor */ -ink.Model = function() {}; - -/** @constructor */ -ink.ElementListener = function() {}; - -/** @constructor */ -ink.proto.scene_change.SceneChangeEvent = function() {}; - -const goog = {}; -goog.events = {}; -goog.disposable = {}; -goog.math = {}; -goog.ui = {}; -goog.html = {}; -goog.proto2 = {}; - -/** @constructor */ -goog.events.EventTarget = function() {}; - -/** @interface */ -goog.disposable.IDisposable = function() {}; - -/** @interface */ -goog.events.Listenable = function() {}; - -/** @constructor */ -goog.math.Size = function() {}; - -/** @constructor */ -goog.events.Event = function() {}; - -/** @constructor */ -goog.proto2.Message = function() {}; - -/** - * @extends {goog.events.EventTarget} - * @constructor - */ -goog.ui.Component = function() {}; - -/** @constructor */ -goog.html.SafeUrl = function() {}; diff --git a/chromium/chrome/browser/resources/pdf/ink/index.html b/chromium/chrome/browser/resources/pdf/ink/index.html index 61d5e7e077b..07f64d813e6 100644 --- a/chromium/chrome/browser/resources/pdf/ink/index.html +++ b/chromium/chrome/browser/resources/pdf/ink/index.html @@ -1,5 +1,5 @@ <!DOCTYPE html> -<script src="glcore_wasm_bootstrap_compiled.js"></script> +<script src="ink_loader.js"></script> <script src="ink_lib_binary.js"></script> <script src="ink_api.js"></script> <style> diff --git a/chromium/chrome/browser/resources/pdf/ink/ink_api.js b/chromium/chrome/browser/resources/pdf/ink/ink_api.js index c394b630077..5d4a4d72a83 100644 --- a/chromium/chrome/browser/resources/pdf/ink/ink_api.js +++ b/chromium/chrome/browser/resources/pdf/ink/ink_api.js @@ -3,36 +3,19 @@ // found in the LICENSE file. /** - * @typedef {{ - * canUndo: boolean, - * canRedo: boolean, - * }} - */ -let UndoState; - -/** * Wraps the Ink component with an API that can be called * across an IFrame boundary. */ class InkAPI { - /** @param {!ink.embed.EmbedComponent} embed */ - constructor(embed) { - this.embed_ = embed; - this.brush_ = ink.BrushModel.getInstance(embed); + /** @param {!drawings.Canvas} canvas */ + constructor(canvas) { + this.canvas_ = canvas; this.camera_ = null; } - /** @param {function(!UndoState)} listener */ + /** @param {function(!drawings.UndoState)} listener */ addUndoStateListener(listener) { - /** @param {!ink.UndoStateChangeEvent} e */ - function wrapper(e) { - listener({ - canUndo: e.getCanUndo(), - canRedo: e.getCanRedo(), - }); - } - - this.embed_.addEventListener(ink.UndoStateChangeEvent.EVENT_TYPE, wrapper); + this.canvas_.addUndoRedoListener(listener); } /** @@ -42,109 +25,70 @@ class InkAPI { // We change the type from ArrayBuffer to Uint8Array due to the consequences // of the buffer being passed across the iframe boundary. This realm has a // different ArrayBuffer constructor than `buffer`. - // TODO(dstockwell): Update Ink to allow Uint8Array here. - this.embed_.setPDF( - /** @type {!ArrayBuffer} */ ( - /** @type {!*} */ (new Uint8Array(buffer)))); + this.canvas_.setPDF(new Uint8Array(buffer)); } /** - * @return {!Promise<Uint8Array>} + * @return {!Uint8Array} */ getPDF() { - return this.embed_.getPDF(); + return this.canvas_.getPDF(); } /** * @return {!Uint8Array} */ getPDFDestructive() { - return this.embed_.getPDFDestructive(); + return this.canvas_.getPDFDestructive(); } async setCamera(camera) { this.camera_ = camera; - this.embed_.setCamera(camera); + this.canvas_.setCamera(camera); // Wait for the next task to avoid a race where Ink drops the camera value // when the canvas is rotated in low-latency mode. - setTimeout(() => this.embed_.setCamera(this.camera_), 0); + setTimeout(() => this.canvas_.setCamera(this.camera_), 0); } /** @param {AnnotationTool} tool */ setAnnotationTool(tool) { - const shape = { - eraser: 'MAGIC_ERASE', - pen: 'INKPEN', - highlighter: 'SMART_HIGHLIGHTER_TOOL', - }[tool.tool]; - this.brush_.setShape(shape); - if (tool.tool !== 'eraser') { - this.brush_.setColor(/** @type {string} */ (tool.color)); - } - this.brush_.setStrokeWidth(tool.size); + this.canvas_.setTool(tool); } flush() { - return new Promise(resolve => this.embed_.flush(resolve)); + return this.canvas_.flush(); } /** @param {string} hexColor */ setOutOfBoundsColor(hexColor) { - this.embed_.setOutOfBoundsColor(ink.Color.fromString(hexColor)); + this.canvas_.setOutOfBoundsColor(hexColor); } /** @param {string} url */ setBorderImage(url) { - this.embed_.setBorderImage(url); + this.canvas_.setBorderImage(url); } /** @param {number} spacing in points */ setPageSpacing(spacing) { - this.embed_.setVerticalPageLayout(spacing); + this.canvas_.setVerticalPageLayout(spacing); } - dispatchPointerEvent(type, init) { - const engine = document.querySelector('#ink-engine'); - const match = engine.style.transform.match(/(\d+)deg/); - const rotation = match ? Number(match[1]) : 0; - let offsetX = init.clientX; - let offsetY = init.clientY; - // If Ink's canvas has been re-orientated away from 0, we must transform - // the event's offsetX and offsetY to correspond with the rotation and - // offset applied. - if ([90, 180, 270].includes(rotation)) { - const width = window.innerWidth; - const height = window.innerHeight; - const matrix = new DOMMatrix(); - matrix.translateSelf(width / 2, height / 2); - matrix.rotateSelf(0, 0, -rotation); - matrix.translateSelf(-width / 2, -height / 2); - const result = matrix.transformPoint({x: offsetX, y: offsetY}); - offsetX = result.x - engine.offsetLeft; - offsetY = result.y - engine.offsetTop; - } - - const event = new PointerEvent(type, init); - // Ink uses offsetX and offsetY, but we can only override them, not pass - // as part of the init. - Object.defineProperty(event, 'offsetX', {value: offsetX}); - Object.defineProperty(event, 'offsetY', {value: offsetY}); - engine.dispatchEvent(event); + dispatchPointerEvent(evt) { + this.canvas_.dispatchInput(evt); } undo() { - this.embed_.undo(); + this.canvas_.undo(); } redo() { - this.embed_.redo(); + this.canvas_.redo(); } } /** @return {Promise<InkAPI>} */ window.initInk = async function() { - const config = new ink.embed.Config(); - const embed = await ink.embed.EmbedComponent.execute(config); - embed.assignFlag(ink.proto.Flag.ENABLE_HOST_CAMERA_CONTROL, true); - return new InkAPI(embed); + const canvas = await drawings.Canvas.execute(document.body); + return new InkAPI(canvas); }; diff --git a/chromium/chrome/browser/resources/pdf/ink_controller.js b/chromium/chrome/browser/resources/pdf/ink_controller.js new file mode 100644 index 00000000000..276b6ab686b --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/ink_controller.js @@ -0,0 +1,128 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'; + +import {ContentController} from './controller.js'; +import {Viewport} from './viewport.js'; + +// Note: Redefining this type here, to work around the fact that ink externs +// are only available on Chrome OS, so the targets that contain them cannot be +// built on other platforms. + +/** + * @typedef {{ + * setAnnotationTool: function(AnnotationTool):void, + * viewportChanged: function():void, + * saveDocument: function():!Promise, + * undo: function():void, + * redo: function():void, + * load: function(string, !ArrayBuffer):!Promise, + * viewport: !Viewport, + * }} + */ +let ViewerInkHostElement; + +// Controller for annotation mode, on Chrome OS only. Fires the following events +// from its event target: +// has-unsaved-changes: Fired to indicate there are ink annotations that have +// not been saved. +// set-annotation-undo-state: Contains information about whether undo or redo +// options are available. +export class InkController extends ContentController { + /** + * @param {!Viewport} viewport + * @param {!HTMLDivElement} contentElement + */ + constructor(viewport, contentElement) { + super(); + + /** @private {!Viewport} */ + this.viewport_ = viewport; + + /** @private {!HTMLDivElement} */ + this.contentElement_ = contentElement; + + /** @private {?ViewerInkHostElement} */ + this.inkHost_ = null; + + /** @private {!EventTarget} */ + this.eventTarget_ = new EventTarget(); + + /** @type {?AnnotationTool} */ + this.tool_ = null; + } + + /** @return {!EventTarget} */ + getEventTarget() { + return this.eventTarget_; + } + + /** @param {AnnotationTool} tool */ + setAnnotationTool(tool) { + this.tool_ = tool; + if (this.inkHost_) { + this.inkHost_.setAnnotationTool(tool); + } + } + + /** @override */ + rotateClockwise() { + // TODO(dstockwell): implement rotation + } + + /** @override */ + rotateCounterclockwise() { + // TODO(dstockwell): implement rotation + } + + /** @override */ + setTwoUpView(enableTwoUpView) { + // TODO(dstockwell): Implement two up view. + } + + /** @override */ + viewportChanged() { + this.inkHost_.viewportChanged(); + } + + /** @override */ + save(requestType) { + return this.inkHost_.saveDocument(); + } + + /** @override */ + undo() { + this.inkHost_.undo(); + } + + /** @override */ + redo() { + this.inkHost_.redo(); + } + + /** @override */ + load(filename, data) { + if (!this.inkHost_) { + const inkHost = document.createElement('viewer-ink-host'); + this.contentElement_.appendChild(inkHost); + this.inkHost_ = /** @type {!ViewerInkHostElement} */ (inkHost); + this.inkHost_.viewport = this.viewport_; + inkHost.addEventListener('stroke-added', e => { + this.eventTarget_.dispatchEvent(new CustomEvent('has-unsaved-changes')); + }); + inkHost.addEventListener('undo-state-changed', e => { + this.eventTarget_.dispatchEvent( + new CustomEvent('set-annotation-undo-state', {detail: e.detail})); + }); + } + return this.inkHost_.load(filename, data); + } + + /** @override */ + unload() { + this.inkHost_.remove(); + this.inkHost_ = null; + } +} diff --git a/chromium/chrome/browser/resources/pdf/main.js b/chromium/chrome/browser/resources/pdf/main.js index 28e1726b30b..4b65231c650 100644 --- a/chromium/chrome/browser/resources/pdf/main.js +++ b/chromium/chrome/browser/resources/pdf/main.js @@ -2,16 +2,75 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import './elements/viewer-error-screen.js'; -import './elements/viewer-password-screen.js'; -import './elements/viewer-pdf-toolbar.js'; -import './elements/viewer-zoom-toolbar.js'; -import './elements/shared-vars.js'; -// <if expr="chromeos"> -import './elements/viewer-ink-host.js'; -import './elements/viewer-form-warning.js'; -// </if> - -import {main} from './main_util.js'; +import './pdf_viewer.js'; + +import {BrowserApi, createBrowserApi} from './browser_api.js'; + +/** + * Stores any pending messages received which should be passed to the + * PDFViewer when it is created. + * @type Array + */ +const pendingMessages = []; + +/** + * Handles events that are received prior to the PDFViewer being created. + * @param {Object} message A message event received. + */ +function handleScriptingMessage(message) { + pendingMessages.push(message); +} + +/** + * Initialize the global PDFViewer and pass any outstanding messages to it. + * @param {!BrowserApi} browserApi + */ +function initViewer(browserApi) { + // PDFViewer will handle any messages after it is created. + window.removeEventListener('message', handleScriptingMessage, false); + const viewer = document.querySelector('#viewer'); + viewer.init(browserApi); + while (pendingMessages.length > 0) { + viewer.handleScriptingMessage(pendingMessages.shift()); + } + window.viewer = viewer; +} + +/** + * Determine if the content settings allow PDFs to execute javascript. + * @param {!BrowserApi} browserApi + * @return {!Promise<!BrowserApi>} + */ +function configureJavaScriptContentSetting(browserApi) { + return new Promise((resolve, reject) => { + chrome.contentSettings.javascript.get( + { + 'primaryUrl': browserApi.getStreamInfo().originalUrl, + 'secondaryUrl': window.location.origin + }, + (result) => { + browserApi.getStreamInfo().javascript = result.setting; + resolve(browserApi); + }); + }); +} + +/** + * Entrypoint for starting the PDF viewer. This function obtains the browser + * API for the PDF and initializes the PDF Viewer. + */ +function main() { + // Set up an event listener to catch scripting messages which are sent prior + // to the PDFViewer being created. + window.addEventListener('message', handleScriptingMessage, false); + let chain = createBrowserApi(); + + // Content settings may not be present in test environments. + if (chrome.contentSettings) { + chain = chain.then(configureJavaScriptContentSetting); + } + + chain.then(initViewer); +} main(); diff --git a/chromium/chrome/browser/resources/pdf/main_pp.js b/chromium/chrome/browser/resources/pdf/main_pp.js deleted file mode 100644 index b21153858b0..00000000000 --- a/chromium/chrome/browser/resources/pdf/main_pp.js +++ /dev/null @@ -1,12 +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. - -import './elements/viewer-error-screen.js'; -import './elements/viewer-page-indicator.js'; -import './elements/viewer-zoom-toolbar.js'; -import './elements/shared-vars.js'; - -import {main} from './main_util.js'; - -main(); diff --git a/chromium/chrome/browser/resources/pdf/main_util.js b/chromium/chrome/browser/resources/pdf/main_util.js deleted file mode 100644 index a0585f05ff4..00000000000 --- a/chromium/chrome/browser/resources/pdf/main_util.js +++ /dev/null @@ -1,83 +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. - -import {BrowserApi, createBrowserApi} from './browser_api.js'; -import {PDFViewer} from './pdf_viewer.js'; - - -/** - * Global PDFViewer object, accessible for testing. - * - * @type Object - */ -window.viewer = null; - - -/** - * Stores any pending messages received which should be passed to the - * PDFViewer when it is created. - * - * @type Array - */ -const pendingMessages = []; - -/** - * Handles events that are received prior to the PDFViewer being created. - * - * @param {Object} message A message event received. - */ -function handleScriptingMessage(message) { - pendingMessages.push(message); -} -/** - * Initialize the global PDFViewer and pass any outstanding messages to it. - * - * @param {!BrowserApi} browserApi - */ -function initViewer(browserApi) { - // PDFViewer will handle any messages after it is created. - window.removeEventListener('message', handleScriptingMessage, false); - window.viewer = new PDFViewer(browserApi); - while (pendingMessages.length > 0) { - window.viewer.handleScriptingMessage(pendingMessages.shift()); - } -} - -/** - * Determine if the content settings allow PDFs to execute javascript. - * - * @param {!BrowserApi} browserApi - * @return {!Promise<!BrowserApi>} - */ -function configureJavaScriptContentSetting(browserApi) { - return new Promise((resolve, reject) => { - chrome.contentSettings.javascript.get( - { - 'primaryUrl': browserApi.getStreamInfo().originalUrl, - 'secondaryUrl': window.location.origin - }, - (result) => { - browserApi.getStreamInfo().javascript = result.setting; - resolve(browserApi); - }); - }); -} - -/** - * Entrypoint for starting the PDF viewer. This function obtains the browser - * API for the PDF and constructs a PDFViewer object with it. - */ -export function main() { - // Set up an event listener to catch scripting messages which are sent prior - // to the PDFViewer being created. - window.addEventListener('message', handleScriptingMessage, false); - let chain = createBrowserApi(); - - // Content settings may not be present in test environments. - if (chrome.contentSettings) { - chain = chain.then(configureJavaScriptContentSetting); - } - - chain.then(initViewer); -} diff --git a/chromium/chrome/browser/resources/pdf/metrics.js b/chromium/chrome/browser/resources/pdf/metrics.js index d1ca0a8270b..42384c4b0db 100644 --- a/chromium/chrome/browser/resources/pdf/metrics.js +++ b/chromium/chrome/browser/resources/pdf/metrics.js @@ -4,13 +4,10 @@ import {FittingType, TwoUpViewAction} from './constants.js'; -/** - * Handles events specific to the PDF viewer and logs the corresponding metrics. - */ +// Handles events specific to the PDF viewer and logs the corresponding metrics. export class PDFMetrics { /** * Records when the zoom mode is changed to fit a FittingType. - * * @param {FittingType} fittingType the new FittingType. */ static recordFitTo(fittingType) { @@ -25,7 +22,6 @@ export class PDFMetrics { /** * Records when the two up view mode is enabled or disabled. - * * @param {TwoUpViewAction} twoUpViewAction the new TwoUpViewAction. */ static recordTwoUpView(twoUpViewAction) { @@ -36,8 +32,18 @@ export class PDFMetrics { } /** + * Records zoom in and zoom out actions. + * @param {boolean} isZoomIn True when the action is zooming in, false when + * the action is zooming out. + */ + static recordZoomAction(isZoomIn) { + PDFMetrics.record( + isZoomIn ? PDFMetrics.UserAction.ZOOM_IN : + PDFMetrics.UserAction.ZOOM_OUT); + } + + /** * Records the given action to chrome.metricsPrivate. - * * @param {PDFMetrics.UserAction} action */ static record(action) { @@ -84,18 +90,15 @@ PDFMetrics.firstActionRecorded_ = new Set(); * The *_FIRST values are recorded automaticlly, * eg. PDFMetrics.record(...ROTATE) will also record ROTATE_FIRST * on the first instance. - * * @enum {number} */ PDFMetrics.UserAction = { - /** - * Recorded when the document is first loaded. This event serves as - * denominator to determine percentages of documents in which an action was - * taken as well as average number of each action per document. - */ + // Recorded when the document is first loaded. This event serves as + // denominator to determine percentages of documents in which an action was + // taken as well as average number of each action per document. DOCUMENT_OPENED: 0, - /** Recorded when the document is rotated clockwise or counter-clockwise. */ + // Recorded when the document is rotated clockwise or counter-clockwise. ROTATE_FIRST: 1, ROTATE: 2, @@ -105,26 +108,24 @@ PDFMetrics.UserAction = { FIT_TO_PAGE_FIRST: 5, FIT_TO_PAGE: 6, - /** Recorded when the bookmarks panel is opened. */ + // Recorded when the bookmarks panel is opened. OPEN_BOOKMARKS_PANEL_FIRST: 7, OPEN_BOOKMARKS_PANEL: 8, - /** Recorded when a bookmark is followed. */ + // Recorded when a bookmark is followed. FOLLOW_BOOKMARK_FIRST: 9, FOLLOW_BOOKMARK: 10, - /** Recorded when the page selection is used to navigate to another page. */ + // Recorded when the page selection is used to navigate to another page. PAGE_SELECTOR_NAVIGATE_FIRST: 11, PAGE_SELECTOR_NAVIGATE: 12, - /** Recorded when the user triggers a save of the document. */ + // Recorded when the user triggers a save of the document. SAVE_FIRST: 13, SAVE: 14, - /** - * Recorded when the user triggers a save of the document and the document - * has been modified by annotations. - */ + // Recorded when the user triggers a save of the document and the document + // has been modified by annotations. SAVE_WITH_ANNOTATION_FIRST: 15, SAVE_WITH_ANNOTATION: 16, @@ -137,39 +138,47 @@ PDFMetrics.UserAction = { EXIT_ANNOTATION_MODE_FIRST: 21, EXIT_ANNOTATION_MODE: 22, - /** Recorded when a pen stroke is made. */ + // Recorded when a pen stroke is made. ANNOTATE_STROKE_TOOL_PEN_FIRST: 23, ANNOTATE_STROKE_TOOL_PEN: 24, - /** Recorded when an eraser stroke is made. */ + // Recorded when an eraser stroke is made. ANNOTATE_STROKE_TOOL_ERASER_FIRST: 25, ANNOTATE_STROKE_TOOL_ERASER: 26, - /** Recorded when a highlighter stroke is made. */ + // Recorded when a highlighter stroke is made. ANNOTATE_STROKE_TOOL_HIGHLIGHTER_FIRST: 27, ANNOTATE_STROKE_TOOL_HIGHLIGHTER: 28, - /** Recorded when a stroke is made using touch. */ + // Recorded when a stroke is made using touch. ANNOTATE_STROKE_DEVICE_TOUCH_FIRST: 29, ANNOTATE_STROKE_DEVICE_TOUCH: 30, - /** Recorded when a stroke is made using mouse. */ + // Recorded when a stroke is made using mouse. ANNOTATE_STROKE_DEVICE_MOUSE_FIRST: 31, ANNOTATE_STROKE_DEVICE_MOUSE: 32, - /** Recorded when a stroke is made using pen. */ + // Recorded when a stroke is made using pen. ANNOTATE_STROKE_DEVICE_PEN_FIRST: 33, ANNOTATE_STROKE_DEVICE_PEN: 34, - /** Recorded when two-up view mode is enabled. */ + // Recorded when two-up view mode is enabled. TWO_UP_VIEW_ENABLE_FIRST: 35, TWO_UP_VIEW_ENABLE: 36, - /** Recorded when two-up view mode is disabled. */ + // Recorded when two-up view mode is disabled. TWO_UP_VIEW_DISABLE_FIRST: 37, TWO_UP_VIEW_DISABLE: 38, - NUMBER_OF_ACTIONS: 39, + // Recorded when zoom in button is clicked. + ZOOM_IN_FIRST: 39, + ZOOM_IN: 40, + + // Recorded when zoom out button is clicked. + ZOOM_OUT_FIRST: 41, + ZOOM_OUT: 42, + + NUMBER_OF_ACTIONS: 43, }; // Map from UserAction to the 'FIRST' action. These metrics are recorded @@ -252,4 +261,12 @@ PDFMetrics.firstMap_ = new Map([ PDFMetrics.UserAction.TWO_UP_VIEW_DISABLE, PDFMetrics.UserAction.TWO_UP_VIEW_DISABLE_FIRST, ], + [ + PDFMetrics.UserAction.ZOOM_IN, + PDFMetrics.UserAction.ZOOM_IN_FIRST, + ], + [ + PDFMetrics.UserAction.ZOOM_OUT, + PDFMetrics.UserAction.ZOOM_OUT_FIRST, + ], ]); diff --git a/chromium/chrome/browser/resources/pdf/navigator.js b/chromium/chrome/browser/resources/pdf/navigator.js index e24d3e8ff02..8aa2c1e3fd6 100644 --- a/chromium/chrome/browser/resources/pdf/navigator.js +++ b/chromium/chrome/browser/resources/pdf/navigator.js @@ -5,10 +5,8 @@ import {OpenPdfParamsParser} from './open_pdf_params_parser.js'; import {Viewport} from './viewport.js'; -/** - * NavigatorDelegate for calling browser-specific functions to do the actual - * navigating. - */ +// NavigatorDelegate for calling browser-specific functions to do the actual +// navigating. export class NavigatorDelegate { /** * @param {number} tabId The tab ID of the PDF viewer or -1 if the viewer is @@ -63,7 +61,7 @@ export class NavigatorDelegate { } } -/** Navigator for navigating to links inside or outside the PDF. */ +// Navigator for navigating to links inside or outside the PDF. export class PdfNavigator { /** * @param {string} originalUrl The original page URL. diff --git a/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js b/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js index 08ef73a94db..858a62b47fd 100644 --- a/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js +++ b/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js @@ -4,10 +4,8 @@ import {FittingType} from './constants.js'; -/** - * Parses the open pdf parameters passed in the url to set initial viewport - * settings for opening the pdf. - */ +// Parses the open pdf parameters passed in the url to set initial viewport +// settings for opening the pdf. export class OpenPdfParamsParser { /** * @param {function(string):void} getNamedDestinationCallback @@ -24,7 +22,6 @@ export class OpenPdfParamsParser { /** * Parse zoom parameter of open PDF parameters. The PDF should be opened at * the specified zoom level. - * * @param {string} paramValue zoom value. * @return {Object} Map with zoom parameters (zoom and position). * @private @@ -57,7 +54,6 @@ export class OpenPdfParamsParser { /** * Parse view parameter of open PDF parameters. The PDF should be opened at * the specified fitting type mode and position. - * * @param {string} paramValue view value. * @return {Object} Map with view parameters (view and viewPosition). * @private @@ -95,57 +91,35 @@ export class OpenPdfParamsParser { } /** - * Parse the parameters encoded in the fragment of a URL into a dictionary. - * + * Parse the parameters encoded in the fragment of a URL. * @param {string} url to parse - * @return {Object} Key-value pairs of URL parameters + * @return {!URLSearchParams} * @private */ parseUrlParams_(url) { - const params = {}; - - const paramIndex = url.search('#'); - if (paramIndex === -1) { - return params; - } - - const paramTokens = url.substring(paramIndex + 1).split('&'); - if ((paramTokens.length === 1) && (paramTokens[0].search('=') === -1)) { - // Handle the case of http://foo.com/bar#NAMEDDEST. This is not - // explicitly mentioned except by example in the Adobe - // "PDF Open Parameters" document. - params['nameddest'] = paramTokens[0]; - return params; - } - - for (const paramToken of paramTokens) { - const keyValueSplit = paramToken.split('='); - if (keyValueSplit.length !== 2) { - continue; + const hash = new URL(url).hash; + const params = new URLSearchParams(hash.substring(1)); + + // Handle the case of http://foo.com/bar#NAMEDDEST. This is not + // explicitly mentioned except by example in the Adobe + // "PDF Open Parameters" document. + if (Array.from(params).length === 1) { + const key = Array.from(params.keys())[0]; + if (params.get(key) === '') { + params.append('nameddest', key); + params.delete(key); } - params[keyValueSplit[0]] = keyValueSplit[1]; } return params; } /** - * Parse PDF url parameters used for controlling the state of UI. These need - * to be available when the UI is being initialized, rather than when the PDF - * is finished loading. - * * @param {string} url that needs to be parsed. - * @return {Object} parsed url parameters. + * @return {boolean} Whether the toolbar UI element should be shown. */ - getUiUrlParams(url) { - const params = this.parseUrlParams_(url); - const uiParams = {toolbar: true}; - - if ('toolbar' in params && params['toolbar'] === '0') { - uiParams.toolbar = false; - } - - return uiParams; + shouldShowToolbar(url) { + return this.parseUrlParams_(url).get('toolbar') !== '0'; } /** @@ -153,7 +127,6 @@ export class OpenPdfParamsParser { * and specify actions to be performed when opening pdf files. * See http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/ * pdfs/pdf_open_parameters.pdf for details. - * * @param {string} url that needs to be parsed. * @param {Function} callback function to be called with viewport info. */ @@ -163,25 +136,30 @@ export class OpenPdfParamsParser { const urlParams = this.parseUrlParams_(url); - if ('page' in urlParams) { + if (urlParams.has('page')) { // |pageNumber| is 1-based, but goToPage() take a zero-based page number. - const pageNumber = parseInt(urlParams['page'], 10); + const pageNumber = parseInt(urlParams.get('page'), 10); if (!Number.isNaN(pageNumber) && pageNumber > 0) { params['page'] = pageNumber - 1; } } - if ('view' in urlParams) { - Object.assign(params, this.parseViewParam_(urlParams['view'])); + if (urlParams.has('view')) { + Object.assign( + params, + this.parseViewParam_(/** @type {string} */ (urlParams.get('view')))); } - if ('zoom' in urlParams) { - Object.assign(params, this.parseZoomParam_(urlParams['zoom'])); + if (urlParams.has('zoom')) { + Object.assign( + params, + this.parseZoomParam_(/** @type {string} */ (urlParams.get('zoom')))); } - if (params.page === undefined && 'nameddest' in urlParams) { + if (params.page === undefined && urlParams.has('nameddest')) { this.outstandingRequests_.push({callback: callback, params: params}); - this.getNamedDestinationCallback_(urlParams['nameddest']); + this.getNamedDestinationCallback_( + /** @type {string} */ (urlParams.get('nameddest'))); } else { callback(params); } @@ -190,7 +168,6 @@ export class OpenPdfParamsParser { /** * This is called when a named destination is received and the page number * corresponding to the request for which a named destination is passed. - * * @param {number} pageNumber The page corresponding to the named destination * requested. */ diff --git a/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js b/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js index 8cae862e05d..6c2cad0de82 100644 --- a/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js +++ b/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js @@ -4,26 +4,27 @@ /** * Turn a dictionary received from postMessage into a key event. - * * @param {Object} dict A dictionary representing the key event. - * @return {!Event} A key event. + * @return {!KeyboardEvent} A key event. */ export function DeserializeKeyEvent(dict) { - const e = document.createEvent('Event'); - e.initEvent('keydown', true, true); - e.keyCode = dict.keyCode; - e.code = dict.code; - e.shiftKey = dict.shiftKey; - e.ctrlKey = dict.ctrlKey; - e.altKey = dict.altKey; - e.metaKey = dict.metaKey; + const e = new KeyboardEvent('keydown', { + bubbles: true, + cancelable: true, + key: dict.key, + code: dict.code, + keyCode: dict.keyCode, + shiftKey: dict.shiftKey, + ctrlKey: dict.ctrlKey, + altKey: dict.altKey, + metaKey: dict.metaKey, + }); e.fromScriptingAPI = true; return e; } /** * Turn a key event into a dictionary which can be sent over postMessage. - * * @param {Event} event A key event. * @return {Object} A dictionary representing the key event. */ @@ -31,6 +32,7 @@ export function SerializeKeyEvent(event) { return { keyCode: event.keyCode, code: event.code, + key: event.key, shiftKey: event.shiftKey, ctrlKey: event.ctrlKey, altKey: event.altKey, @@ -49,11 +51,8 @@ export const LoadState = { FAILED: 'failed' }; -/** - * Create a new PDFScriptingAPI. This provides a scripting interface to - * the PDF viewer so that it can be customized by things like print preview. - * - */ +// Provides a scripting interface to the PDF viewer so that it can be customized +// by things like print preview. export class PDFScriptingAPI { /** * @param {Window} window the window of the page containing the pdf viewer. @@ -134,7 +133,6 @@ export class PDFScriptingAPI { * Send a message to the extension. If messages try to get sent before there * is a plugin element set, then we queue them up and send them later (this * can happen in print preview). - * * @param {Object} message The message to send. * @private */ @@ -149,7 +147,6 @@ export class PDFScriptingAPI { /** * Sets the plugin element containing the PDF viewer. The element will usually * be passed into the PDFScriptingAPI constructor but may also be set later. - * * @param {Object} plugin the plugin element containing the PDF viewer. */ setPlugin(plugin) { @@ -168,7 +165,6 @@ export class PDFScriptingAPI { /** * Sets the callback which will be run when the PDF viewport changes. - * * @param {Function} callback the callback to be called. */ setViewportChangedCallback(callback) { @@ -198,7 +194,6 @@ export class PDFScriptingAPI { /** * Resets the PDF viewer into print preview mode. - * * @param {string} url the url of the PDF to load. * @param {boolean} grayscale whether or not to display the PDF in grayscale. * @param {Array<number>} pageNumbers an array of the page numbers. @@ -215,16 +210,13 @@ export class PDFScriptingAPI { }); } - /** - * Hide the toolbars after a delay. - */ + /** Hide the toolbars after a delay. */ hideToolbars() { this.sendMessage_({type: 'hideToolbars'}); } /** * Load a page into the document while in print preview mode. - * * @param {string} url the url of the pdf page to load. * @param {number} index the index of the page to load. */ @@ -248,7 +240,6 @@ export class PDFScriptingAPI { /** * Get the selected text in the document. The callback will be called with the * text that is selected. May only be called after document load. - * * @param {Function} callback a callback to be called with the selected text. * @return {boolean} true if the function is successful, false if there is an * outstanding request for selected text that has not been answered. @@ -262,16 +253,13 @@ export class PDFScriptingAPI { return true; } - /** - * Print the document. May only be called after document load. - */ + /** Print the document. May only be called after document load. */ print() { this.sendMessage_({type: 'print'}); } /** * Send a key event to the extension. - * * @param {Event} keyEvent the key event to send to the extension. */ sendKeyEvent(keyEvent) { @@ -293,7 +281,6 @@ export class PDFScriptingAPI { * iframe which is navigated to the PDF viewer extension and 2) a scripting * interface which provides access to various features of the viewer for use * by print preview and accessibility. - * * @param {string} src the source URL of the PDF to load initially. * @param {string} baseUrl the base URL of the PDF viewer * @return {!HTMLIFrameElement} the iframe element containing the PDF viewer. diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer.html b/chromium/chrome/browser/resources/pdf/pdf_viewer.html new file mode 100644 index 00000000000..a56670db71c --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer.html @@ -0,0 +1,61 @@ +<style include="pdf-viewer-shared-style"> + viewer-pdf-toolbar, + viewer-pdf-toolbar-new { + position: fixed; + width: 100%; + z-index: 4; + } + + viewer-ink-host { + height: 100%; + position: absolute; + width: 100%; + } + + @media(max-height: 250px) { + viewer-pdf-toolbar { + display: none; + } + } +</style> + +<template is="dom-if" if="[[!pdfViewerUpdateEnabled_]]"> + <viewer-pdf-toolbar id="toolbar" strings="[[strings]]" + annotation-available="[[annotationAvailable_]]" + bookmarks="[[bookmarks_]]" doc-title="[[title_]]" + has-edits="[[hasEdits_]]" + has-entered-annotation-mode="[[hasEnteredAnnotationMode_]]" + is-form-field-focused="[[isFormFieldFocused_]]" + on-save="onToolbarSave_" on-print="onPrint_" + on-annotation-mode-toggled="onAnnotationModeToggled_" + on-annotation-tool-changed="onAnnotationToolChanged_" + on-rotate-right="rotateClockwise" on-undo="onUndo_" on-redo="onRedo_" + hidden> + </viewer-pdf-toolbar> +</template> +<template is="dom-if" if="[[pdfViewerUpdateEnabled_]]"> + <viewer-pdf-toolbar-new id="toolbar" hidden> + </viewer-pdf-toolbar-new> +</template> + +<div id="sizer"></div> +<viewer-password-screen id="password-screen" + on-password-submitted="onPasswordSubmitted_"> +</viewer-password-screen> + +<viewer-zoom-toolbar id="zoom-toolbar" strings="[[strings]]" + annotation-mode="[[annotationMode_]]" + on-fit-to-changed="onFitToChanged" + on-two-up-view-changed="onTwoUpViewChanged_" + on-zoom-in="onZoomIn" on-zoom-out="onZoomOut" + hidden> +</viewer-zoom-toolbar> + +<viewer-error-screen id="error-screen"></viewer-error-screen> + +<if expr="chromeos"> +<viewer-form-warning id="form-warning"></viewer-form-warning> +</if> + +<div id="content"></div> + diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer.js b/chromium/chrome/browser/resources/pdf/pdf_viewer.js index e6fc90845ab..e23b4b41e48 100644 --- a/chromium/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer.js @@ -2,46 +2,38 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import './elements/viewer-error-screen.js'; +import './elements/viewer-password-screen.js'; +import './elements/viewer-pdf-toolbar.js'; +import './elements/viewer-pdf-toolbar-new.js'; +import './elements/shared-vars.js'; +// <if expr="chromeos"> +import './elements/viewer-ink-host.js'; +import './elements/viewer-form-warning.js'; +// </if> +import './pdf_viewer_shared_style.js'; + import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; -import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js'; -import {$, hasKeyModifiers, isRTL} from 'chrome://resources/js/util.m.js'; +import {hasKeyModifiers, isRTL} from 'chrome://resources/js/util.m.js'; +import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Bookmark} from './bookmark_type.js'; import {BrowserApi} from './browser_api.js'; -import {FittingType, TwoUpViewAction} from './constants.js'; -import {ContentController, InkController, MessageData, PluginController, PrintPreviewParams} from './controller.js'; -import {FitToChangedEvent} from './elements/viewer-zoom-toolbar.js'; -import {GestureDetector} from './gesture_detector.js'; +import {FittingType, SaveRequestType, TwoUpViewAction} from './constants.js'; import {PDFMetrics} from './metrics.js'; import {NavigatorDelegate, PdfNavigator} from './navigator.js'; import {OpenPdfParamsParser} from './open_pdf_params_parser.js'; import {DeserializeKeyEvent, LoadState, SerializeKeyEvent} from './pdf_scripting_api.js'; +import {PDFViewerBaseElement} from './pdf_viewer_base.js'; +import {DestinationMessageData, DocumentDimensionsMessageData, shouldIgnoreKeyEvents} from './pdf_viewer_utils.js'; import {ToolbarManager} from './toolbar_manager.js'; -import {LayoutOptions, Point, Viewport} from './viewport.js'; -import {ViewportScroller} from './viewport_scroller.js'; -import {ZoomManager} from './zoom_manager.js'; +import {Point} from './viewport.js'; -/** - * @typedef {{ - * source: Object, - * origin: string, - * data: !MessageData, - * }} - */ -let MessageObject; +// <if expr="chromeos"> +import {InkController} from './ink_controller.js'; +// </if> -/** - * @typedef {{ - * type: string, - * height: number, - * width: number, - * layoutOptions: (!LayoutOptions|undefined), - * pageDimensions: Array - * }} - */ -let DocumentDimensionsMessageData; /** * @typedef {{ @@ -55,17 +47,6 @@ let NavigateMessageData; /** * @typedef {{ * type: string, - * page: number, - * x: number, - * y: number, - * zoom: number - * }} - */ -let DestinationMessageData; - -/** - * @typedef {{ - * type: string, * title: string, * bookmarks: !Array<!Bookmark>, * canSerializeDocument: boolean, @@ -82,22 +63,9 @@ let MetadataMessageData; */ let RequiredSaveResult; -/** @return {number} Width of a scrollbar in pixels */ -function getScrollbarWidth() { - const div = document.createElement('div'); - div.style.visibility = 'hidden'; - div.style.overflow = 'scroll'; - div.style.width = '50px'; - div.style.height = '50px'; - div.style.position = 'absolute'; - document.body.appendChild(div); - const result = div.offsetWidth - div.clientWidth; - div.parentNode.removeChild(div); - return result; -} - /** * Return the filename component of a URL, percent decoded if possible. + * Exported for tests. * @param {string} url The URL to get the filename from. * @return {string} The filename component. */ @@ -116,270 +84,187 @@ export function getFilenameFromURL(url) { } } -/** - * Whether keydown events should currently be ignored. Events are ignored when - * an editable element has focus, to allow for proper editing controls. - * @param {Element} activeElement The currently selected DOM node. - * @return {boolean} True if keydown events should be ignored. - */ -export function shouldIgnoreKeyEvents(activeElement) { - while (activeElement.shadowRoot != null && - activeElement.shadowRoot.activeElement != null) { - activeElement = activeElement.shadowRoot.activeElement; +class PDFViewerElement extends PDFViewerBaseElement { + static get is() { + return 'pdf-viewer'; } - return ( - activeElement.isContentEditable || - (activeElement.tagName === 'INPUT' && activeElement.type !== 'radio') || - activeElement.tagName === 'TEXTAREA'); -} + static get template() { + return html`{__html_template__}`; + } -/** - * Creates a new PDFViewer. There should only be one of these objects per - * document. - */ -export class PDFViewer { - /** - * @param {!BrowserApi} browserApi An object providing an API to the browser. - */ - constructor(browserApi) { - /** @private {!BrowserApi} */ - this.browserApi_ = browserApi; + static get properties() { + return { + annotationAvailable_: { + type: Boolean, + computed: 'computeAnnotationAvailable_(' + + 'hadPassword_, rotated_, canSerializeDocument_)', + }, - /** @private {string} */ - this.originalUrl_ = this.browserApi_.getStreamInfo().originalUrl; + annotationMode_: { + type: Boolean, + value: false, + }, - /** @private {string} */ - this.javascript_ = this.browserApi_.getStreamInfo().javascript || 'block'; + bookmarks_: Array, - /** @private {!LoadState} */ - this.loadState_ = LoadState.LOADING; + hasEdits_: { + type: Boolean, + value: false, + }, - /** @private {?Object} */ - this.parentWindow_ = null; + hasEnteredAnnotationMode_: { + type: Boolean, + value: false, + }, - /** @private {?string} */ - this.parentOrigin_ = null; + rotated_: Boolean, - /** @private {boolean} */ - this.isFormFieldFocused_ = false; + hadPassword_: Boolean, - /** @private {number} */ - this.beepCount_ = 0; + canSerializeDocument_: Boolean, - /** @private {!Array} */ - this.delayedScriptingMessages_ = []; + title_: String, - /** @private {!PromiseResolver} */ - this.loaded_; + isFormFieldFocused_: Boolean, - /** @private {boolean} */ - this.initialLoadComplete_ = false; + /** @private */ + pdfViewerUpdateEnabled_: { + type: Boolean, + value: function() { + return document.documentElement.hasAttribute( + 'pdf-viewer-update-enabled'); + }, + }, + }; + } + constructor() { + super(); + + // Polymer properties /** @private {boolean} */ - this.isPrintPreview_ = location.origin === 'chrome://print'; - document.documentElement.toggleAttribute( - 'is-print-preview', this.isPrintPreview_); + this.annotationAvailable_; /** @private {boolean} */ - this.isPrintPreviewLoadingFinished_ = false; + this.annotationMode_ = false; + + /** @private {!Array<!Bookmark>} */ + this.bookmarks_ = []; /** @private {boolean} */ - this.isUserInitiatedEvent_ = true; + this.hasEdits_ = false; /** @private {boolean} */ this.hasEnteredAnnotationMode_ = false; /** @private {boolean} */ + this.rotated_ = false; + + /** @private {boolean} */ this.hadPassword_ = false; /** @private {boolean} */ this.canSerializeDocument_ = false; - /** @private {!EventTracker} */ - this.tracker_ = new EventTracker(); - - PDFMetrics.record(PDFMetrics.UserAction.DOCUMENT_OPENED); - - // Parse open pdf parameters. - /** @private {!OpenPdfParamsParser} */ - this.paramsParser_ = new OpenPdfParamsParser( - destination => this.pluginController_.getNamedDestination(destination)); - const toolbarEnabled = - this.paramsParser_.getUiUrlParams(this.originalUrl_).toolbar && - !this.isPrintPreview_; - - // The sizer element is placed behind the plugin element to cause scrollbars - // to be displayed in the window. It is sized according to the document size - // of the pdf and zoom level. - this.sizer_ = /** @type {!HTMLDivElement} */ ($('sizer')); - - /** @private {?ViewerPageIndicatorElement} */ - this.pageIndicator_ = this.isPrintPreview_ ? - /** @type {!ViewerPageIndicatorElement} */ ($('page-indicator')) : - null; - - /** @private {?ViewerPasswordScreenElement} */ - this.passwordScreen_ = - /** @type {?ViewerPasswordScreenElement} */ ($('password-screen')); - if (this.passwordScreen_) { - this.passwordScreen_.addEventListener('password-submitted', e => { - this.onPasswordSubmitted_( - /** @type {!CustomEvent<{password: string}>} */ (e)); - }); - } + /** @private {string} */ + this.title_ = ''; - /** @private {?ViewerErrorScreenElement} */ - this.errorScreen_ = - /** @type {!ViewerErrorScreenElement} */ ($('error-screen')); - // Can only reload if we are in a normal tab. - if (chrome.tabs && this.browserApi_.getStreamInfo().tabId !== -1) { - this.errorScreen_.reloadFn = () => { - chrome.tabs.reload(this.browserApi_.getStreamInfo().tabId); - }; - } + /** @private {boolean} */ + this.isFormFieldFocused_ = false; - // Create the viewport. - const shortWindow = - window.innerHeight < PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT; - const topToolbarHeight = - (toolbarEnabled) ? PDFViewer.MATERIAL_TOOLBAR_HEIGHT : 0; - const defaultZoom = - this.browserApi_.getZoomBehavior() === BrowserApi.ZoomBehavior.MANAGE ? - this.browserApi_.getDefaultZoom() : - 1.0; - - /** @private {!Viewport} */ - this.viewport_ = new Viewport( - window, this.sizer_, getScrollbarWidth(), defaultZoom, - topToolbarHeight); - this.viewport_.setViewportChangedCallback(() => this.viewportChanged_()); - this.viewport_.setBeforeZoomCallback( - () => this.currentController_.beforeZoom()); - this.viewport_.setAfterZoomCallback( - () => this.currentController_.afterZoom()); - this.viewport_.setUserInitiatedCallback( - userInitiated => this.setUserInitiated_(userInitiated)); - window.addEventListener('beforeunload', () => this.resetTrackers_()); - - // 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 - // positioning, acting as a viewport. The plugin renders into this viewport - // according to the scroll position of the window. - /** @private {!HTMLEmbedElement} */ - this.plugin_ = - /** @type {!HTMLEmbedElement} */ (document.createElement('embed')); - - // NOTE: The plugin's 'id' field must be set to 'plugin' since - // chrome/renderer/printing/print_render_frame_helper.cc actually - // references it. - this.plugin_.id = 'plugin'; - this.plugin_.type = 'application/x-google-chrome-pdf'; - - // Handle scripting messages from outside the extension that wish to - // interact with it. We also send a message indicating that extension has - // loaded and is ready to receive messages. - window.addEventListener('message', message => { - this.handleScriptingMessage(/** @type {!MessageObject} */ (message)); - }, false); - - this.plugin_.setAttribute('src', this.originalUrl_); - this.plugin_.setAttribute( - 'stream-url', this.browserApi_.getStreamInfo().streamUrl); - let headers = ''; - for (const header in this.browserApi_.getStreamInfo().responseHeaders) { - headers += header + ': ' + - this.browserApi_.getStreamInfo().responseHeaders[header] + '\n'; - } - this.plugin_.setAttribute('headers', headers); + // Non-Polymer properties - this.plugin_.setAttribute('background-color', PDFViewer.BACKGROUND_COLOR); - this.plugin_.setAttribute('top-toolbar-height', topToolbarHeight); - this.plugin_.setAttribute('javascript', this.javascript_); + /** @private {number} */ + this.beepCount_ = 0; - if (this.browserApi_.getStreamInfo().embedded) { - this.plugin_.setAttribute( - 'top-level-url', this.browserApi_.getStreamInfo().tabUrl); - } else { - this.plugin_.setAttribute('full-frame', ''); - } + /** @private {boolean} */ + this.hadPassword_ = false; + + /** @private {boolean} */ + this.toolbarEnabled_ = false; + + // <if expr="chromeos"> + /** @private {?InkController} */ + this.inkController_ = null; + // </if> + + /** @private {?ToolbarManager} */ + this.toolbarManager_ = null; + + /** @private {?PdfNavigator} */ + this.navigator_ = null; + + /** @private {string} */ + this.title_ = ''; + + /** @private {boolean} */ + this.pdfViewerUpdateEnabled_; + } - $('content').appendChild(this.plugin_); + /** @override */ + getToolbarHeight() { + assert(this.paramsParser); + this.toolbarEnabled_ = + this.paramsParser.shouldShowToolbar(this.originalUrl); + return this.toolbarEnabled_ ? MATERIAL_TOOLBAR_HEIGHT : 0; + } + + /** @override */ + getContent() { + return /** @type {!HTMLDivElement} */ (this.$$('#content')); + } - /** @private {!PluginController} */ - this.pluginController_ = new PluginController( - this.plugin_, this.viewport_, () => this.isUserInitiatedEvent_, - () => this.loaded); - this.tracker_.add( - this.pluginController_.getEventTarget(), 'plugin-message', - e => this.handlePluginMessage_(e)); + /** @override */ + getSizer() { + return /** @type {!HTMLDivElement} */ (this.$$('#sizer')); + } + + /** @override */ + getZoomToolbar() { + return /** @type {!ViewerZoomToolbarElement} */ (this.$$('#zoom-toolbar')); + } - /** @private {!InkController} */ - this.inkController_ = new InkController(this.viewport_); - this.tracker_.add( + /** @override */ + getErrorScreen() { + return /** @type {!ViewerErrorScreenElement} */ (this.$$('#error-screen')); + } + + /** + * @return {!ViewerPdfToolbarElement} + * @private + */ + getToolbar_() { + return /** @type {!ViewerPdfToolbarElement} */ (this.$$('#toolbar')); + } + + /** @override */ + getBackgroundColor() { + return BACKGROUND_COLOR; + } + + /** @param {!BrowserApi} browserApi */ + init(browserApi) { + super.init(browserApi); + + // <if expr="chromeos"> + this.inkController_ = new InkController( + this.viewport, /** @type {!HTMLDivElement} */ (this.getContent())); + this.tracker.add( this.inkController_.getEventTarget(), 'stroke-added', () => chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(true)); - this.tracker_.add( + this.tracker.add( this.inkController_.getEventTarget(), 'set-annotation-undo-state', e => this.setAnnotationUndoState_(e)); + // </if> - /** @private {!ContentController} */ - this.currentController_ = this.pluginController_; - - // Setup the button event listeners. - /** @private {!ViewerZoomToolbarElement} */ - this.zoomToolbar_ = - /** @type {!ViewerZoomToolbarElement} */ ($('zoom-toolbar')); - this.zoomToolbar_.isPrintPreview = this.isPrintPreview_; - this.zoomToolbar_.addEventListener( - 'fit-to-changed', - e => this.fitToChanged_( - /** @type {!CustomEvent<FitToChangedEvent>} */ (e))); - this.zoomToolbar_.addEventListener( - 'two-up-view-changed', - e => this.twoUpViewChanged_( - /** @type {!CustomEvent<!TwoUpViewAction>} */ (e))); - this.zoomToolbar_.addEventListener( - 'zoom-in', () => this.viewport_.zoomIn()); - this.zoomToolbar_.addEventListener( - 'zoom-out', () => this.viewport_.zoomOut()); - - /** @private {!GestureDetector} */ - this.gestureDetector_ = new GestureDetector(assert($('content'))); - this.gestureDetector_.addEventListener( - 'pinchstart', e => this.onPinchStart_(e)); - this.sentPinchEvent_ = false; - this.gestureDetector_.addEventListener( - 'pinchupdate', e => this.onPinchUpdate_(e)); - this.gestureDetector_.addEventListener( - 'pinchend', e => this.onPinchEnd_(e)); - - /** @private {?ViewerPdfToolbarElement} */ - this.toolbar_ = null; - if (toolbarEnabled) { - this.toolbar_ = /** @type {!ViewerPdfToolbarElement} */ ($('toolbar')); - this.toolbar_.hidden = false; - this.toolbar_.addEventListener('save', () => this.save_()); - this.toolbar_.addEventListener('print', () => this.print_()); - this.toolbar_.addEventListener( - 'undo', () => this.currentController_.undo()); - this.toolbar_.addEventListener( - 'redo', () => this.currentController_.redo()); - this.toolbar_.addEventListener( - 'rotate-right', () => this.rotateClockwise_()); - this.toolbar_.addEventListener('annotation-mode-toggled', e => { - this.annotationModeToggled_( - /** @type {!CustomEvent<{value: boolean}>} */ (e)); - }); - this.toolbar_.addEventListener( - 'annotation-tool-changed', - e => this.inkController_.setAnnotationTool(e.detail.value)); - - this.toolbar_.docTitle = getFilenameFromURL(this.originalUrl_); + this.title_ = getFilenameFromURL(this.originalUrl); + if (this.toolbarEnabled_) { + this.getToolbar_().hidden = false; } document.body.addEventListener('change-page', e => { - this.viewport_.goToPage(e.detail.page); + this.viewport.goToPage(e.detail.page); if (e.detail.origin === 'bookmark') { PDFMetrics.record(PDFMetrics.UserAction.FOLLOW_BOOKMARK); } else if (e.detail.origin === 'pageselector') { @@ -387,12 +272,8 @@ export class PDFViewer { } }); - document.body.addEventListener('change-zoom', e => { - this.viewport_.setZoom(e.detail.zoom); - }); - document.body.addEventListener('change-page-and-xy', e => { - const point = this.viewport_.convertPageToScreen(e.detail.page, e.detail); + const point = this.viewport.convertPageToScreen(e.detail.page, e.detail); this.goToPageAndXY_(e.detail.origin, e.detail.page, point); }); @@ -409,59 +290,21 @@ export class PDFViewer { } }); - /** @private {!ToolbarManager} */ - this.toolbarManager_ = - new ToolbarManager(window, this.toolbar_, this.zoomToolbar_); - - // Set up the ZoomManager. - /** @private {!ZoomManager} */ - this.zoomManager_ = ZoomManager.create( - this.browserApi_.getZoomBehavior(), () => this.viewport_.getZoom(), - zoom => this.browserApi_.setZoom(zoom), - this.browserApi_.getInitialZoom()); - this.viewport_.setZoomManager(this.zoomManager_); - this.browserApi_.addZoomEventListener( - zoom => this.zoomManager_.onBrowserZoomChange(zoom)); + this.toolbarManager_ = new ToolbarManager( + window, this.pdfViewerUpdateEnabled_ ? null : this.getToolbar_(), + this.getZoomToolbar()); // Setup the keyboard event listener. document.addEventListener( 'keydown', e => this.handleKeyEvent_(/** @type {!KeyboardEvent} */ (e))); - document.addEventListener('mousemove', e => this.handleMouseEvent_(e)); - document.addEventListener('mouseout', e => this.handleMouseEvent_(e)); - document.addEventListener( - 'contextmenu', e => this.handleContextMenuEvent_(e)); - const tabId = this.browserApi_.getStreamInfo().tabId; - /** @private {!PdfNavigator} */ + const tabId = this.browserApi.getStreamInfo().tabId; this.navigator_ = new PdfNavigator( - this.originalUrl_, this.viewport_, this.paramsParser_, + this.originalUrl, this.viewport, + /** @type {!OpenPdfParamsParser} */ (this.paramsParser), new NavigatorDelegate(tabId)); - /** @private {!ViewportScroller} */ - this.viewportScroller_ = - new ViewportScroller(this.viewport_, this.plugin_, window); - - /** @private {!Array<!Bookmark>} */ - this.bookmarks_; - - /** @private {!Point} */ - this.lastViewportPosition_; - - /** @private {boolean} */ - this.inPrintPreviewMode_; - - /** @private {boolean} */ - this.dark_; - - /** @private {!DocumentDimensionsMessageData} */ - this.documentDimensions_; - - // Request translated strings. - chrome.resourcesPrivate.getStrings( - chrome.resourcesPrivate.Component.PDF, - strings => this.handleStrings_(strings)); - // Listen for save commands from the browser. if (chrome.mimeHandlerPrivate && chrome.mimeHandlerPrivate.onSave) { chrome.mimeHandlerPrivate.onSave.addListener(url => this.onSave_(url)); @@ -475,168 +318,57 @@ export class PDFViewer { * @private */ handleKeyEvent_(e) { - const position = this.viewport_.position; - // Certain scroll events may be sent from outside of the extension. - const fromScriptingAPI = e.fromScriptingAPI; - if (shouldIgnoreKeyEvents(document.activeElement) || e.defaultPrevented) { return; } this.toolbarManager_.hideToolbarsAfterTimeout(); - const pageUpHandler = () => { - // Go to the previous page if we are fit-to-page or fit-to-height. - if (this.viewport_.isPagedMode()) { - this.viewport_.goToPreviousPage(); - // Since we do the movement of the page. - e.preventDefault(); - } else if (fromScriptingAPI) { - position.y -= this.viewport_.size.height; - this.viewport_.position = position; - } - }; - const pageDownHandler = () => { - // Go to the next page if we are fit-to-page or fit-to-height. - if (this.viewport_.isPagedMode()) { - this.viewport_.goToNextPage(); - // Since we do the movement of the page. - e.preventDefault(); - } else if (fromScriptingAPI) { - position.y += this.viewport_.size.height; - this.viewport_.position = position; - } - }; + // Let the viewport handle directional key events. + if (this.viewport.handleDirectionalKeyEvent(e, this.isFormFieldFocused_)) { + return; + } - switch (e.keyCode) { - case 9: // Tab key. + switch (e.key) { + case 'Tab': this.toolbarManager_.showToolbarsForKeyboardNavigation(); return; - case 27: // Escape key. - if (!this.isPrintPreview_) { - this.toolbarManager_.hideSingleToolbarLayer(); - return; - } - break; // Ensure escape falls through to the print-preview handler. - case 32: // Space key. - if (e.shiftKey) { - pageUpHandler(); - } else { - pageDownHandler(); - } - return; - case 33: // Page up key. - pageUpHandler(); - return; - case 34: // Page down key. - pageDownHandler(); - return; - case 37: // Left arrow key. - if (!hasKeyModifiers(e)) { - // Go to the previous page if there are no horizontal scrollbars and - // no form field is focused. - if (!(this.viewport_.documentHasScrollbars().horizontal || - this.isFormFieldFocused_)) { - this.viewport_.goToPreviousPage(); - // Since we do the movement of the page. - e.preventDefault(); - } else if (fromScriptingAPI) { - position.x -= Viewport.SCROLL_INCREMENT; - this.viewport_.position = position; - } - } + case 'Escape': + this.toolbarManager_.hideSingleToolbarLayer(); return; - case 38: // Up arrow key. - if (fromScriptingAPI) { - position.y -= Viewport.SCROLL_INCREMENT; - this.viewport_.position = position; - } - return; - case 39: // Right arrow key. - if (!hasKeyModifiers(e)) { - // Go to the next page if there are no horizontal scrollbars and no - // form field is focused. - if (!(this.viewport_.documentHasScrollbars().horizontal || - this.isFormFieldFocused_)) { - this.viewport_.goToNextPage(); - // Since we do the movement of the page. - e.preventDefault(); - } else if (fromScriptingAPI) { - position.x += Viewport.SCROLL_INCREMENT; - this.viewport_.position = position; - } - } - return; - case 40: // Down arrow key. - if (fromScriptingAPI) { - position.y += Viewport.SCROLL_INCREMENT; - this.viewport_.position = position; - } - return; - case 65: // 'a' key. + case 'a': if (e.ctrlKey || e.metaKey) { - this.pluginController_.selectAll(); + this.pluginController.selectAll(); // Since we do selection ourselves. e.preventDefault(); } return; - case 71: // 'g' key. - if (this.toolbar_ && (e.ctrlKey || e.metaKey) && e.altKey) { + case 'g': + if (this.toolbarEnabled_ && (e.ctrlKey || e.metaKey) && e.altKey) { this.toolbarManager_.showToolbars(); - this.toolbar_.selectPageNumber(); + this.getToolbar_().selectPageNumber(); } return; - case 219: // Left bracket key. + case '[': if (e.ctrlKey) { - this.rotateCounterclockwise_(); + this.rotateCounterclockwise(); } return; - case 220: // Backslash key. + case '\\': if (e.ctrlKey) { - this.zoomToolbar_.fitToggleFromHotKey(); + this.getZoomToolbar().fitToggleFromHotKey(); } return; - case 221: // Right bracket key. + case ']': if (e.ctrlKey) { - this.rotateClockwise_(); + this.rotateClockwise(); } return; } - // Give print preview a chance to handle the key event. - if (!fromScriptingAPI && this.isPrintPreview_) { - this.sendScriptingMessage_( - {type: 'sendKeyEvent', keyEvent: SerializeKeyEvent(e)}); - } else { - // Show toolbars as a fallback. - if (!(e.shiftKey || e.ctrlKey || e.altKey)) { - this.toolbarManager_.showToolbars(); - } - } - } - - handleMouseEvent_(e) { - if (e.type === 'mousemove') { - this.toolbarManager_.handleMouseMove(e); - } else if (e.type === 'mouseout') { - this.toolbarManager_.hideToolbarsForMouseOut(); - } - } - - /** - * @param {!Event} e The context menu event - * @private - */ - handleContextMenuEvent_(e) { - // Stop Chrome from popping up the context menu on long press. We need to - // make sure the start event did not have 2 touches because we don't want - // to block two finger tap opening the context menu. We check for - // firesTouchEvents in order to not block the context menu on right click. - const capabilities = - /** @type {{ sourceCapabilities: Object }} */ (e).sourceCapabilities; - if (capabilities.firesTouchEvents && - !this.gestureDetector_.wasTwoFingerTouch()) { - e.preventDefault(); + // Show toolbars as a fallback. + if (!(e.shiftKey || e.ctrlKey || e.altKey)) { + this.toolbarManager_.showToolbars(); } } @@ -645,59 +377,61 @@ export class PDFViewer { * @param {!CustomEvent<{value: boolean}>} e * @private */ - async annotationModeToggled_(e) { + async onAnnotationModeToggled_(e) { const annotationMode = e.detail.value; - this.zoomToolbar_.annotationMode = annotationMode; + this.annotationMode_ = annotationMode; if (annotationMode) { // Enter annotation mode. - assert(this.currentController_ === this.pluginController_); + assert(this.currentController === this.pluginController); // TODO(dstockwell): set plugin read-only, begin transition - this.updateProgress_(0); + this.updateProgress(0); // TODO(dstockwell): handle save failure - const saveResult = await this.pluginController_.save(true); - // Data always exists when save is called with requireResult = true. + const saveResult = + await this.pluginController.save(SaveRequestType.ANNOTATION); + // Data always exists when save is called with requestType = ANNOTATION. const result = /** @type {!RequiredSaveResult} */ (saveResult); if (result.hasUnsavedChanges) { assert(!loadTimeData.getBoolean('pdfFormSaveEnabled')); try { - await $('form-warning').show(); + await this.$$('#form-warning').show(); } catch (e) { // The user aborted entering annotation mode. Revert to the plugin. - this.toolbar_.annotationMode = false; - this.zoomToolbar_.annotationMode = false; - this.updateProgress_(100); + this.getToolbar_().annotationMode = false; + this.annotationMode_ = false; + this.updateProgress(100); return; } } PDFMetrics.record(PDFMetrics.UserAction.ENTER_ANNOTATION_MODE); this.hasEnteredAnnotationMode_ = true; // TODO(dstockwell): feed real progress data from the Ink component - this.updateProgress_(50); + this.updateProgress(50); await this.inkController_.load(result.fileName, result.dataToSave); this.inkController_.setAnnotationTool( - assert(this.toolbar_.annotationTool)); - this.currentController_ = this.inkController_; - this.pluginController_.unload(); - this.updateProgress_(100); + assert(this.getToolbar_().annotationTool)); + this.currentController = this.inkController_; + this.pluginController.unload(); + this.updateProgress(100); } else { // Exit annotation mode. PDFMetrics.record(PDFMetrics.UserAction.EXIT_ANNOTATION_MODE); - assert(this.currentController_ === this.inkController_); + assert(this.currentController === this.inkController_); // TODO(dstockwell): set ink read-only, begin transition - this.updateProgress_(0); + this.updateProgress(0); // This runs separately to allow other consumers of `loaded` to queue // up after this task. this.loaded.then(() => { - this.currentController_ = this.pluginController_; + this.currentController = this.pluginController; this.inkController_.unload(); }); // TODO(dstockwell): handle save failure - const saveResult = await this.inkController_.save(true); - // Data always exists when save is called with requireResult = true. + const saveResult = + await this.inkController_.save(SaveRequestType.ANNOTATION); + // Data always exists when save is called with requestType = ANNOTATION. const result = /** @type {!RequiredSaveResult} */ (saveResult); - await this.pluginController_.load(result.fileName, result.dataToSave); + await this.pluginController.load(result.fileName, result.dataToSave); // Ensure the plugin gets the initial viewport. - this.pluginController_.afterZoom(); + this.pluginController.afterZoom(); } } @@ -706,32 +440,21 @@ export class PDFViewer { * @return {Promise<void>} */ async exitAnnotationMode_() { - if (!this.toolbar_.annotationMode) { + if (!this.getToolbar_().annotationMode) { return; } - this.toolbar_.toggleAnnotation(); - this.zoomToolbar_.annotationMode = false; + this.getToolbar_().toggleAnnotation(); + this.annotationMode_ = false; await this.loaded; } - /** - * Request to change the viewport fitting type. - * @param {!CustomEvent<FitToChangedEvent>} e - * @private - */ - fitToChanged_(e) { - if (e.detail.fittingType === FittingType.FIT_TO_PAGE) { - this.viewport_.fitToPage(); - this.toolbarManager_.forceHideTopToolbar(); - } else if (e.detail.fittingType === FittingType.FIT_TO_WIDTH) { - this.viewport_.fitToWidth(); - } else if (e.detail.fittingType === FittingType.FIT_TO_HEIGHT) { - this.viewport_.fitToHeight(); - this.toolbarManager_.forceHideTopToolbar(); - } + /** @override */ + onFitToChanged(e) { + super.onFitToChanged(e); - if (e.detail.userInitiated) { - PDFMetrics.recordFitTo(e.detail.fittingType); + if (e.detail.fittingType === FittingType.FIT_TO_PAGE || + e.detail.fittingType === FittingType.FIT_TO_HEIGHT) { + this.toolbarManager_.forceHideTopToolbar(); } } @@ -741,70 +464,17 @@ export class PDFViewer { * @param {!CustomEvent<!TwoUpViewAction>} e * @private */ - twoUpViewChanged_(e) { - this.currentController_.setTwoUpView( + onTwoUpViewChanged_(e) { + this.currentController.setTwoUpView( e.detail === TwoUpViewAction.TWO_UP_VIEW_ENABLE); this.toolbarManager_.forceHideTopToolbar(); - this.toolbar_.annotationAvailable = + this.getToolbar_().annotationAvailable = (e.detail !== TwoUpViewAction.TWO_UP_VIEW_ENABLE); PDFMetrics.recordTwoUpView(e.detail); } /** - * Sends a 'documentLoaded' message to the PDFScriptingAPI if the document has - * finished loading. - * @private - */ - sendDocumentLoadedMessage_() { - if (this.loadState_ === LoadState.LOADING) { - return; - } - if (this.isPrintPreview_ && !this.isPrintPreviewLoadingFinished_) { - return; - } - this.sendScriptingMessage_( - {type: 'documentLoaded', load_state: this.loadState_}); - } - - /** - * Handle open pdf parameters. This function updates the viewport as per - * the parameters mentioned in the url while opening pdf. The order is - * important as later actions can override the effects of previous actions. - * @param {Object} params The open params passed in the URL. - * @private - */ - handleURLParams_(params) { - if (params.zoom) { - this.viewport_.setZoom(params.zoom); - } - - if (params.position) { - this.viewport_.goToPageAndXY( - params.page ? params.page : 0, params.position.x, params.position.y); - } else if (params.page) { - this.viewport_.goToPage(params.page); - } - - if (params.view) { - this.isUserInitiatedEvent_ = false; - this.zoomToolbar_.forceFit(params.view); - if (params.viewPosition) { - const zoomedPositionShift = - params.viewPosition * this.viewport_.getZoom(); - const currentViewportPosition = this.viewport_.position; - if (params.view === FittingType.FIT_TO_WIDTH) { - currentViewportPosition.y += zoomedPositionShift; - } else if (params.view === FittingType.FIT_TO_HEIGHT) { - currentViewportPosition.x += zoomedPositionShift; - } - this.viewport_.position = currentViewportPosition; - } - this.isUserInitiatedEvent_ = true; - } - } - - /** * Moves the viewport to a point in a page. Called back after a * 'transformPagePointReply' is returned from the plugin. * @param {string} origin Identifier for the caller for logging purposes. @@ -814,146 +484,38 @@ export class PDFViewer { * @private */ goToPageAndXY_(origin, page, message) { - this.viewport_.goToPageAndXY(page, message.x, message.y); + this.viewport.goToPageAndXY(page, message.x, message.y); if (origin === 'bookmark') { PDFMetrics.record(PDFMetrics.UserAction.FOLLOW_BOOKMARK); } } - /** - * @return {?Promise} Resolved when the load state reaches LOADED, - * rejects on FAILED. Returns null if no promise has been created, which - * is the case for initial load of the PDF. - */ - get loaded() { - return this.loaded_ ? this.loaded_.promise : null; - } - /** @return {!Viewport} The viewport. Used for testing. */ - get viewport() { - return this.viewport_; - } - /** @return {!Array<!Bookmark>} The bookmarks. Used for testing. */ get bookmarks() { return this.bookmarks_; } - /** - * Updates the load state and triggers completion of the `loaded` - * promise if necessary. - * @param {!LoadState} loadState - * @private - */ - setLoadState_(loadState) { - if (this.loadState_ === loadState) { - return; - } - assert( - loadState === LoadState.LOADING || - this.loadState_ === LoadState.LOADING); - this.loadState_ = loadState; - if (!this.initialLoadComplete_) { - this.initialLoadComplete_ = true; - return; - } - if (loadState === LoadState.SUCCESS) { - this.loaded_.resolve(); - } else if (loadState === LoadState.FAILED) { - this.loaded_.reject(); - } else { - this.loaded_ = new PromiseResolver(); - } - } - - /** - * Update the loading progress of the document in response to a progress - * message being received from the content controller. - * @param {number} progress the progress as a percentage. - * @private - */ - updateProgress_(progress) { - if (this.toolbar_) { - this.toolbar_.loadProgress = progress; - } - - if (progress === -1) { - // Document load failed. - this.errorScreen_.show(); - this.sizer_.style.display = 'none'; - if (this.passwordScreen_ && this.passwordScreen_.active) { - this.passwordScreen_.deny(); - this.passwordScreen_.close(); - } - this.setLoadState_(LoadState.FAILED); - this.isPrintPreviewLoadingFinished_ = true; - this.sendDocumentLoadedMessage_(); - } else if (progress === 100) { - // Document load complete. - if (this.lastViewportPosition_) { - this.viewport_.position = this.lastViewportPosition_; + /** @override */ + setLoadState(loadState) { + super.setLoadState(loadState); + if (loadState === LoadState.FAILED) { + const passwordScreen = this.$$('#password-screen'); + if (passwordScreen && passwordScreen.active) { + passwordScreen.deny(); + passwordScreen.close(); } - this.paramsParser_.getViewportFromUrlParams( - this.originalUrl_, params => this.handleURLParams_(params)); - this.setLoadState_(LoadState.SUCCESS); - this.sendDocumentLoadedMessage_(); - while (this.delayedScriptingMessages_.length > 0) { - this.handleScriptingMessage(this.delayedScriptingMessages_.shift()); - } - - this.toolbarManager_.hideToolbarsAfterTimeout(); - } else { - this.setLoadState_(LoadState.LOADING); } } - /** @private */ - sendBackgroundColorForPrintPreview_() { - this.pluginController_.backgroundColorChanged( - this.dark_ ? PDFViewer.PRINT_PREVIEW_DARK_BACKGROUND_COLOR : - PDFViewer.PRINT_PREVIEW_BACKGROUND_COLOR); - } - - /** - * Load a dictionary of translated strings into the UI. Used as a callback for - * chrome.resourcesPrivate. - * @param {Object} strings Dictionary of translated strings - * @private - */ - handleStrings_(strings) { - const stringsDictionary = - /** @type {{ textdirection: string, language: string }} */ (strings); - document.documentElement.dir = stringsDictionary.textdirection; - document.documentElement.lang = stringsDictionary.language; - - loadTimeData.data = strings; - - // Predefined zoom factors to be used when zooming in/out. These are in - // ascending order. - const presetZoomFactors = /** @type {!Array<number>} */ ( - JSON.parse(loadTimeData.getString('presetZoomFactors'))); - this.viewport_.setZoomFactorRange(presetZoomFactors); - - if (this.isPrintPreview_) { - this.sendBackgroundColorForPrintPreview_(); - } else { - $('toolbar').strings = strings; - $('toolbar').pdfAnnotationsEnabled = - loadTimeData.getBoolean('pdfAnnotationsEnabled'); - $('toolbar').printingEnabled = loadTimeData.getBoolean('printingEnabled'); - } - $('zoom-toolbar').setStrings(strings); - $('zoom-toolbar').twoUpViewEnabled = - loadTimeData.getBoolean('pdfTwoUpViewEnabled') && !this.isPrintPreview_; - // Display the zoom toolbar after the UI text direction is set, to ensure it - // appears on the correct side of the PDF viewer. - $('zoom-toolbar').hidden = false; - if (this.passwordScreen_) { - $('password-screen').strings = strings; + /** @override */ + updateProgress(progress) { + if (this.toolbarEnabled_) { + this.getToolbar_().loadProgress = progress; } - $('error-screen').strings = strings; - if ($('form-warning')) { - $('form-warning').strings = strings; + super.updateProgress(progress); + if (progress === 100) { + this.toolbarManager_.hideToolbarsAfterTimeout(); } } @@ -964,73 +526,14 @@ export class PDFViewer { * @private */ onPasswordSubmitted_(event) { - this.pluginController_.getPasswordComplete(event.detail.password); - } - - /** - * A callback that sets |isUserInitiatedEvent_| to |userInitiated|. - * @param {boolean} userInitiated The value to set |isUserInitiatedEvent_| to. - * @private - */ - setUserInitiated_(userInitiated) { - assert(this.isUserInitiatedEvent_ !== userInitiated); - this.isUserInitiatedEvent_ = userInitiated; - } - - /** - * A callback that's called when an update to a pinch zoom is detected. - * @param {!Object} e the pinch event. - * @private - */ - onPinchUpdate_(e) { - // Throttle number of pinch events to one per frame. - if (!this.sentPinchEvent_) { - this.sentPinchEvent_ = true; - window.requestAnimationFrame(() => { - this.sentPinchEvent_ = false; - this.viewport_.pinchZoom(e); - }); - } - } - - /** - * A callback that's called when the end of a pinch zoom is detected. - * @param {!Object} e the pinch event. - * @private - */ - onPinchEnd_(e) { - // Using rAF for pinch end prevents pinch updates scheduled by rAF getting - // sent after the pinch end. - window.requestAnimationFrame(() => { - this.viewport_.pinchZoomEnd(e); - }); + this.pluginController.getPasswordComplete(event.detail.password); } - /** - * A callback that's called when the start of a pinch zoom is detected. - * @param {!Object} e the pinch event. - * @private - */ - onPinchStart_(e) { - // We also use rAF for pinch start, so that if there is a pinch end event - // scheduled by rAF, this pinch start will be sent after. - window.requestAnimationFrame(() => { - this.viewport_.pinchZoomStart(e); - }); - } - - /** - * A callback that's called after the viewport changes. - * @private - */ - viewportChanged_() { - if (!this.documentDimensions_) { - return; - } - + /** @override */ + updateUIForViewportChange() { // Offset the toolbar position so that it doesn't move if scrollbars appear. - const hasScrollbars = this.viewport_.documentHasScrollbars(); - const scrollbarWidth = this.viewport_.scrollbarWidth; + const hasScrollbars = this.viewport.documentHasScrollbars(); + const scrollbarWidth = this.viewport.scrollbarWidth; const verticalScrollbarWidth = hasScrollbars.vertical ? scrollbarWidth : 0; const horizontalScrollbarWidth = hasScrollbars.horizontal ? scrollbarWidth : 0; @@ -1039,217 +542,70 @@ export class PDFViewer { // gives a compromise: if there is no scrollbar visible then the toolbar // will be half a scrollbar width further left than the spec but if there // is a scrollbar visible it will be half a scrollbar width further right - // than the spec. In RTL layout normally, and in LTR layout in Print Preview - // when the NewPrintPreview flag is enabled, the zoom toolbar is on the left + // than the spec. In RTL layout normally, the zoom toolbar is on the left // left side, but the scrollbar is still on the right, so this is not // necessary. - if (isRTL() === this.isPrintPreview_) { - this.zoomToolbar_.style.right = + const zoomToolbar = this.getZoomToolbar(); + if (!isRTL()) { + zoomToolbar.style.right = -verticalScrollbarWidth + (scrollbarWidth / 2) + 'px'; } // Having a horizontal scrollbar is much rarer so we don't offset the // toolbar from the bottom any more than what the spec says. This means // that when there is a scrollbar visible, it will be a full scrollbar // width closer to the bottom of the screen than usual, but this is ok. - this.zoomToolbar_.style.bottom = -horizontalScrollbarWidth + 'px'; + zoomToolbar.style.bottom = -horizontalScrollbarWidth + 'px'; // Update the page indicator. - const visiblePage = this.viewport_.getMostVisiblePage(); - - if (this.toolbar_) { - this.toolbar_.pageNo = visiblePage + 1; - } - - // TODO(raymes): Give pageIndicator_ the same API as toolbar_. - if (this.pageIndicator_) { - const lastIndex = this.pageIndicator_.index; - this.pageIndicator_.index = visiblePage; - if (this.documentDimensions_.pageDimensions.length > 1 && - hasScrollbars.vertical && lastIndex !== undefined) { - this.pageIndicator_.style.visibility = 'visible'; - } else { - this.pageIndicator_.style.visibility = 'hidden'; - } + const visiblePage = this.viewport.getMostVisiblePage(); + if (this.toolbarEnabled_) { + this.getToolbar_().pageNo = visiblePage + 1; } - this.currentController_.viewportChanged(); - - const visiblePageDimensions = this.viewport_.getPageScreenRect(visiblePage); - const size = this.viewport_.size; - this.sendScriptingMessage_({ - type: 'viewport', - pageX: visiblePageDimensions.x, - pageY: visiblePageDimensions.y, - pageWidth: visiblePageDimensions.width, - viewportWidth: size.width, - viewportHeight: size.height - }); + this.currentController.viewportChanged(); } - /** - * Handle a scripting message from outside the extension (typically sent by - * PDFScriptingAPI in a page containing the extension) to interact with the - * plugin. - * @param {!MessageObject} message The message to handle. - */ + /** @override */ handleScriptingMessage(message) { - if (this.parentWindow_ !== message.source) { - this.parentWindow_ = message.source; - this.parentOrigin_ = message.origin; - // Ensure that we notify the embedder if the document is loaded. - if (this.loadState_ !== LoadState.LOADING) { - this.sendDocumentLoadedMessage_(); - } - } + super.handleScriptingMessage(message); - if (this.handlePrintPreviewScriptingMessage_(message)) { - return; - } - - // Delay scripting messages from users of the scripting API until the - // document is loaded. This simplifies use of the APIs. - if (this.loadState_ !== LoadState.SUCCESS) { - this.delayedScriptingMessages_.push(message); + if (this.delayScriptingMessage(message)) { return; } switch (message.data.type.toString()) { case 'getSelectedText': - this.pluginController_.getSelectedText(); + this.pluginController.getSelectedText(); break; case 'print': - this.pluginController_.print(); + this.pluginController.print(); break; case 'selectAll': - this.pluginController_.selectAll(); + this.pluginController.selectAll(); break; } } - /** - * Handle scripting messages specific to print preview. - * @param {!MessageObject} message the message to handle. - * @return {boolean} true if the message was handled, false otherwise. - * @private - */ - handlePrintPreviewScriptingMessage_(message) { - if (!this.isPrintPreview_) { - return false; - } - - let messageData = message.data; - switch (messageData.type.toString()) { - case 'loadPreviewPage': - messageData = - /** @type {{ url: string, index: number }} */ (messageData); - this.pluginController_.loadPreviewPage( - messageData.url, messageData.index); - return true; - case 'resetPrintPreviewMode': - messageData = /** @type {!PrintPreviewParams} */ (messageData); - this.setLoadState_(LoadState.LOADING); - if (!this.inPrintPreviewMode_) { - this.inPrintPreviewMode_ = true; - this.isUserInitiatedEvent_ = false; - this.zoomToolbar_.forceFit(FittingType.FIT_TO_PAGE); - this.isUserInitiatedEvent_ = true; - } - - // Stash the scroll location so that it can be restored when the new - // document is loaded. - this.lastViewportPosition_ = this.viewport_.position; - - // TODO(raymes): Disable these properly in the plugin. - const printButton = $('print-button'); - if (printButton) { - printButton.parentNode.removeChild(printButton); - } - const saveButton = $('save-button'); - if (saveButton) { - saveButton.parentNode.removeChild(saveButton); - } - - this.pageIndicator_.pageLabels = messageData.pageNumbers; - - this.pluginController_.resetPrintPreviewMode(messageData); - return true; - case 'sendKeyEvent': - this.handleKeyEvent_(/** @type {!KeyboardEvent} */ (DeserializeKeyEvent( - /** @type {{ keyEvent: Object }} */ (message.data).keyEvent))); - return true; - case 'hideToolbars': - this.toolbarManager_.resetKeyboardNavigationAndHideToolbars(); - return true; - case 'darkModeChanged': - this.dark_ = /** @type {{darkMode: boolean}} */ (message.data).darkMode; - if (this.isPrintPreview_) { - this.sendBackgroundColorForPrintPreview_(); - } - return true; - case 'scrollPosition': - const position = this.viewport_.position; - messageData = /** @type {{ x: number, y: number }} */ (message.data); - position.y += messageData.y; - position.x += messageData.x; - this.viewport_.position = position; - return true; - } - - return false; - } - - /** - * Send a scripting message outside the extension (typically to - * PDFScriptingAPI in a page containing the extension). - * @param {Object} message the message to send. - * @private - */ - sendScriptingMessage_(message) { - if (this.parentWindow_ && this.parentOrigin_) { - let targetOrigin; - // Only send data back to the embedder if it is from the same origin, - // unless we're sending it to ourselves (which could happen in the case - // of tests). We also allow documentLoaded messages through as this won't - // leak important information. - if (this.parentOrigin_ === window.location.origin) { - targetOrigin = this.parentOrigin_; - } else if (message.type === 'documentLoaded') { - targetOrigin = '*'; - } else { - targetOrigin = this.originalUrl_; - } - try { - this.parentWindow_.postMessage(message, targetOrigin); - } catch (ok) { - // TODO(crbug.com/1004425): targetOrigin probably was rejected, such as - // a "data:" URL. This shouldn't cause this method to throw, though. - } - } - } - - /** - * @param {!CustomEvent<MessageData>} e - * @private - */ - handlePluginMessage_(e) { + /** @override */ + handlePluginMessage(e) { const data = e.detail; switch (data.type.toString()) { case 'beep': this.handleBeep_(); return; case 'documentDimensions': - this.setDocumentDimensions_( + this.setDocumentDimensions( /** @type {!DocumentDimensionsMessageData} */ (data)); return; case 'getPassword': this.handlePasswordRequest_(); return; case 'getSelectedTextReply': - this.handleSelectedTextReply_( + this.handleSelectedTextReply( /** @type {{ selectedText: string }} */ (data).selectedText); return; case 'loadProgress': - this.updateProgress_( + this.updateProgress( /** @type {{ progress: number }} */ (data).progress); return; case 'navigate': @@ -1258,52 +614,56 @@ export class PDFViewer { return; case 'navigateToDestination': const destinationData = /** @type {!DestinationMessageData} */ (data); - this.handleNavigateToDestination_( + this.viewport.handleNavigateToDestination( destinationData.page, destinationData.x, destinationData.y, destinationData.zoom); return; - case 'printPreviewLoaded': - this.handlePrintPreviewLoaded_(); - return; case 'metadata': const metadata = /** @type {!MetadataMessageData} */ (data); this.setDocumentMetadata_( metadata.title, metadata.bookmarks, metadata.canSerializeDocument); return; + case 'setIsEditing': + // Editing mode can only be entered once, and cannot be exited. + this.hasEdits_ = true; + return; case 'setIsSelecting': - this.setIsSelecting_( + this.viewportScroller.setEnableScrolling( /** @type {{ isSelecting: boolean }} */ (data).isSelecting); return; case 'getNamedDestinationReply': - this.paramsParser_.onNamedDestinationReceived( + this.paramsParser.onNamedDestinationReceived( /** @type {{ pageNumber: number }} */ (data).pageNumber); return; case 'formFocusChange': this.isFormFieldFocused_ = /** @type {{ focused: boolean }} */ (data).focused; return; + case 'touchSelectionOccurred': + this.sendScriptingMessage({ + type: 'touchSelectionOccurred', + }); + return; + case 'documentFocusChanged': + // TODO(crbug.com/1069370): Draw a focus rect around plugin. + return; } assertNotReached('Unknown message type received: ' + data.type); } - /** - * Sets document dimensions from the current controller. - * @param {!DocumentDimensionsMessageData} documentDimensions - * @private - */ - setDocumentDimensions_(documentDimensions) { - this.documentDimensions_ = documentDimensions; - this.isUserInitiatedEvent_ = false; - this.viewport_.setDocumentDimensions(this.documentDimensions_); - this.isUserInitiatedEvent_ = true; + /** @override */ + setDocumentDimensions(documentDimensions) { + super.setDocumentDimensions(documentDimensions); // If we received the document dimensions, the password was good so we // can dismiss the password screen. - if (this.passwordScreen_ && this.passwordScreen_.active) { - this.passwordScreen_.close(); + const passwordScreen = this.$$('#password-screen'); + if (passwordScreen && passwordScreen.active) { + passwordScreen.close(); } - if (this.toolbar_) { - this.toolbar_.docLength = this.documentDimensions_.pageDimensions.length; + if (this.toolbarEnabled_) { + this.getToolbar_().docLength = + this.documentDimensions.pageDimensions.length; } } @@ -1323,74 +683,24 @@ export class PDFViewer { handlePasswordRequest_() { // If the password screen isn't up, put it up. Otherwise we're // responding to an incorrect password so deny it. - assert(!!this.passwordScreen_); - if (!this.passwordScreen_.active) { + const passwordScreen = this.$$('#password-screen'); + assert(passwordScreen); + if (!passwordScreen.active) { this.hadPassword_ = true; - this.updateAnnotationAvailable_(); - this.passwordScreen_.show(); + passwordScreen.show(); } else { - this.passwordScreen_.deny(); + passwordScreen.deny(); } } /** - * Handles a selected text reply from the current controller. - * @param {string} selectedText - * @private - */ - handleSelectedTextReply_(selectedText) { - this.sendScriptingMessage_({ - type: 'getSelectedTextReply', - selectedText: selectedText, - }); - } - - /** * Handles a navigation request from the current controller. * @param {string} url * @param {!PdfNavigator.WindowOpenDisposition} disposition * @private */ handleNavigate_(url, disposition) { - // If in print preview, always open a new tab. - if (this.isPrintPreview_) { - this.navigator_.navigate( - url, PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB); - } else { - this.navigator_.navigate(url, disposition); - } - } - - /** - * Handles an internal navigation request to a destination from the current - * controller. - * - * @param {number} page - * @param {number} x - * @param {number} y - * @param {number} zoom - * @private - */ - handleNavigateToDestination_(page, x, y, zoom) { - if (zoom) { - this.viewport_.setZoom(zoom); - } - - if (x || y) { - this.viewport_.goToPageAndXY(page, x ? x : 0, y ? y : 0); - } else { - this.viewport_.goToPage(page); - } - } - - /** - * Handles a notification that print preview has loaded from the - * current controller. - * @private - */ - handlePrintPreviewLoaded_() { - this.isPrintPreviewLoadingFinished_ = true; - this.sendDocumentLoadedMessage_(); + this.navigator_.navigate(url, disposition); } /** @@ -1401,27 +711,10 @@ export class PDFViewer { * @private */ setDocumentMetadata_(title, bookmarks, canSerializeDocument) { - if (title) { - document.title = title; - } else { - document.title = getFilenameFromURL(this.originalUrl_); - } + this.title_ = title ? title : getFilenameFromURL(this.originalUrl); + document.title = this.title_; this.bookmarks_ = bookmarks; - if (this.toolbar_) { - this.toolbar_.docTitle = document.title; - this.toolbar_.bookmarks = this.bookmarks_; - } this.canSerializeDocument_ = canSerializeDocument; - this.updateAnnotationAvailable_(); - } - - /** - * Sets the is selecting flag from the current controller. - * @param {boolean} isSelecting - * @private - */ - setIsSelecting_(isSelecting) { - this.viewportScroller_.setEnableScrolling(isSelecting); } /** @@ -1431,28 +724,58 @@ export class PDFViewer { * @private */ async onSave_(streamUrl) { - if (streamUrl !== this.browserApi_.getStreamInfo().streamUrl) { + if (streamUrl !== this.browserApi.getStreamInfo().streamUrl) { return; } - this.save_(); + let saveMode; + if (this.hasEnteredAnnotationMode_) { + saveMode = SaveRequestType.ANNOTATION; + } else if ( + loadTimeData.getBoolean('pdfFormSaveEnabled') && this.hasEdits_) { + saveMode = SaveRequestType.EDITED; + } else { + saveMode = SaveRequestType.ORIGINAL; + } + + this.save_(saveMode); + } + + /** + * @param {!CustomEvent<!SaveRequestType>} e + * @private + */ + onToolbarSave_(e) { + this.save_(e.detail); } /** * Saves the current PDF document to disk. + * @param {SaveRequestType} requestType The type of save request. * @private */ - async save_() { + async save_(requestType) { PDFMetrics.record(PDFMetrics.UserAction.SAVE); - if (this.hasEnteredAnnotationMode_) { + // If we have entered annotation mode we must require the local + // contents to ensure annotations are saved, unless the user specifically + // requested the original document. Otherwise we would save the cached + // remote copy without annotations. + if (requestType === SaveRequestType.ANNOTATION) { PDFMetrics.record(PDFMetrics.UserAction.SAVE_WITH_ANNOTATION); } - // If we have entered annotation mode we must require the local - // contents to ensure annotations are saved. Otherwise we would - // save the cached or remote copy without annotatios. - const requireResult = this.hasEnteredAnnotationMode_; + // Always send requests of type ORIGINAL to the plugin controller, not the + // ink controller. The ink controller always saves the edited document. // TODO(dstockwell): Report an error to user if this fails. - const result = await this.currentController_.save(requireResult); + let result; + if (requestType !== SaveRequestType.ORIGINAL || !this.annotationMode_) { + result = await this.currentController.save(requestType); + } else { + // Request type original in annotation mode --> need to exit annotation + // mode before saving. See https://crbug.com/919364. + await this.exitAnnotationMode_(); + assert(!this.annotationMode_); + result = await this.currentController.save(SaveRequestType.ORIGINAL); + } if (result == null) { // The content controller handled the save internally. return; @@ -1465,7 +788,12 @@ export class PDFViewer { } chrome.fileSystem.chooseEntry( - {type: 'saveFile', suggestedName: fileName}, entry => { + { + type: 'saveFile', + accepts: [{description: '*.pdf', extensions: ['pdf']}], + suggestedName: fileName + }, + entry => { if (chrome.runtime.lastError) { if (chrome.runtime.lastError.message !== 'User cancelled') { console.log( @@ -1488,97 +816,83 @@ export class PDFViewer { } /** @private */ - async print_() { + async onPrint_() { PDFMetrics.record(PDFMetrics.UserAction.PRINT); await this.exitAnnotationMode_(); - this.currentController_.print(); + this.currentController.print(); } /** * Updates the toolbar's annotation available flag depending on current * conditions. + * @return {boolean} Whether annotations are available. * @private */ - updateAnnotationAvailable_() { - if (!this.toolbar_) { - return; - } - let annotationAvailable = true; - if (this.viewport_.getClockwiseRotations() !== 0) { - annotationAvailable = false; - } - if (this.hadPassword_) { - annotationAvailable = false; - } - if (!this.canSerializeDocument_) { - annotationAvailable = false; - } - this.toolbar_.annotationAvailable = annotationAvailable; + computeAnnotationAvailable_() { + return this.canSerializeDocument_ && !this.rotated_ && !this.hadPassword_; } /** @private */ - rotateClockwise_() { - PDFMetrics.record(PDFMetrics.UserAction.ROTATE); - this.viewport_.rotateClockwise(); - this.currentController_.rotateClockwise(); - this.updateAnnotationAvailable_(); + onUndo_() { + this.currentController.undo(); } /** @private */ - rotateCounterclockwise_() { - PDFMetrics.record(PDFMetrics.UserAction.ROTATE); - this.viewport_.rotateCounterclockwise(); - this.currentController_.rotateCounterclockwise(); - this.updateAnnotationAvailable_(); + onRedo_() { + this.currentController.redo(); + } + + /** + * @param {!CustomEvent<{value: AnnotationTool}>} e + * @private + */ + onAnnotationToolChanged_(e) { + this.inkController_.setAnnotationTool(e.detail.value); } + // <if expr="chromeos"> /** * @param {!CustomEvent<{canUndo: boolean, canRedo: boolean}>} e * @private */ setAnnotationUndoState_(e) { - this.toolbar_.canUndoAnnotation = e.detail.canUndo; - this.toolbar_.canRedoAnnotation = e.detail.canRedo; + this.getToolbar_().canUndoAnnotation = e.detail.canUndo; + this.getToolbar_().canRedoAnnotation = e.detail.canRedo; } + // </if> - /** @private */ - resetTrackers_() { - this.viewport_.resetTracker(); - if (this.tracker_) { - this.tracker_.removeAll(); - } + /** @override */ + rotateClockwise() { + super.rotateClockwise(); + this.rotated_ = this.viewport.getClockwiseRotations() !== 0; } -} -// Export on |window| such that scripts injected from pdf_extension_test.cc can -// access it. -window.PDFViewer = PDFViewer; + /** @override */ + rotateCounterclockwise() { + super.rotateCounterclockwise(); + this.rotated_ = this.viewport.getClockwiseRotations() !== 0; + } +} /** * The height of the toolbar along the top of the page. The document will be * shifted down by this much in the viewport. + * @type {number} */ -PDFViewer.MATERIAL_TOOLBAR_HEIGHT = 56; +const MATERIAL_TOOLBAR_HEIGHT = 56; /** * Minimum height for the material toolbar to show (px). Should match the media * query in index-material.css. If the window is smaller than this at load, * leave no space for the toolbar. + * @type {number} */ -PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT = 250; - -/** - * The background color used for print preview (--google-grey-refresh-300). - */ -PDFViewer.PRINT_PREVIEW_BACKGROUND_COLOR = '0xFFDADCE0'; - -/** - * The background color used for print preview when dark mode is enabled - * (--google-grey-refresh-700). - */ -PDFViewer.PRINT_PREVIEW_DARK_BACKGROUND_COLOR = '0xFF5F6368'; +const TOOLBAR_WINDOW_MIN_HEIGHT = 250; /** * The background color used for the regular viewer. + * @type {string} */ -PDFViewer.BACKGROUND_COLOR = '0xFF525659'; +const BACKGROUND_COLOR = '0xFF525659'; + +customElements.define(PDFViewerElement.is, PDFViewerElement); diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer_base.js b/chromium/chrome/browser/resources/pdf/pdf_viewer_base.js new file mode 100644 index 00000000000..bb0c9a91d12 --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer_base.js @@ -0,0 +1,640 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {BrowserApi} from './browser_api.js'; +import {FittingType} from './constants.js'; +import {ContentController, MessageData, PluginController} from './controller.js'; +import {FitToChangedEvent} from './elements/viewer-zoom-toolbar.js'; +import {PDFMetrics} from './metrics.js'; +import {OpenPdfParamsParser} from './open_pdf_params_parser.js'; +import {LoadState} from './pdf_scripting_api.js'; +import {DocumentDimensionsMessageData, MessageObject} from './pdf_viewer_utils.js'; +import {Point, Viewport} from './viewport.js'; +import {ViewportScroller} from './viewport_scroller.js'; +import {ZoomManager} from './zoom_manager.js'; + +/** @return {number} Width of a scrollbar in pixels */ +function getScrollbarWidth() { + const div = document.createElement('div'); + div.style.visibility = 'hidden'; + div.style.overflow = 'scroll'; + div.style.width = '50px'; + div.style.height = '50px'; + div.style.position = 'absolute'; + document.body.appendChild(div); + const result = div.offsetWidth - div.clientWidth; + div.parentNode.removeChild(div); + return result; +} + +export class PDFViewerBaseElement extends PolymerElement { + static get is() { + return 'pdf-viewer-base'; + } + + static get template() { + return null; + } + + static get properties() { + return { + strings: Object, + }; + } + + constructor() { + super(); + + /** @protected {Object|undefined} */ + this.strings = undefined; + + /** @protected {?BrowserApi} */ + this.browserApi = null; + + /** @protected {?ContentController} */ + this.currentController = null; + + /** @protected {string} */ + this.originalUrl = ''; + + /** @protected {!EventTracker} */ + this.tracker = new EventTracker(); + + /** @protected {boolean} */ + this.isUserInitiatedEvent = true; + + /** @protected {?Point} */ + this.lastViewportPosition = null; + + /** @protected {?OpenPdfParamsParser} */ + this.paramsParser = null; + + /** @protected {?ViewportScroller} */ + this.viewportScroller = null; + + /** @protected {?DocumentDimensionsMessageData} */ + this.documentDimensions = null; + + /** @private {boolean} */ + this.overrideSendScriptingMessageForTest_ = false; + + /** @private {!LoadState} */ + this.loadState_ = LoadState.LOADING; + + /** @private {?Object} */ + this.parentWindow_ = null; + + /** @private {?string} */ + this.parentOrigin_ = null; + + /** @private {!Array} */ + this.delayedScriptingMessages_ = []; + + /** @private {?PromiseResolver} */ + this.loaded_ = null; + + /** @private {boolean} */ + this.initialLoadComplete_ = false; + + /** @private {?Viewport} */ + this.viewport_ = null; + + /** @private {?PluginController} */ + this.pluginController_ = null; + + /** @private {?HTMLEmbedElement} */ + this.plugin_ = null; + + /** @private {?ZoomManager} */ + this.zoomManager_ = null; + } + + /** @return {number} The height of the top toolbar */ + getToolbarHeight() { + return 0; + } + + /** + * @return {!HTMLDivElement} + * @protected + */ + getContent() {} + + /** + * @return {!HTMLDivElement} + * @protected + */ + getSizer() {} + + /** + * @return {!ViewerZoomToolbarElement} + * @protected + */ + getZoomToolbar() {} + + /** + * @return {!ViewerErrorScreenElement} + * @protected + */ + getErrorScreen() {} + + /** + * @param {string} query + * @return {?Element} + * @protected + */ + $$(query) { + return this.shadowRoot.querySelector(query); + } + + /** @return {string} */ + getBackgroundColor() { + return ''; + } + + /** + * @return {!HTMLEmbedElement} The plugin + * @private + */ + createPlugin_() { + // 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 + // positioning, acting as a viewport. The plugin renders into this viewport + // according to the scroll position of the window. + const plugin = + /** @type {!HTMLEmbedElement} */ (document.createElement('embed')); + + // NOTE: The plugin's 'id' field must be set to 'plugin' since + // ChromePrintRenderFrameHelperDeleage::GetPdfElement() in + // chrome/renderer/printing/chrome_print_render_frame_helper_delegate.cc + // actually references it. + plugin.id = 'plugin'; + plugin.type = 'application/x-google-chrome-pdf'; + + plugin.setAttribute('src', this.originalUrl); + plugin.setAttribute( + 'stream-url', this.browserApi.getStreamInfo().streamUrl); + let headers = ''; + for (const header in this.browserApi.getStreamInfo().responseHeaders) { + headers += header + ': ' + + this.browserApi.getStreamInfo().responseHeaders[header] + '\n'; + } + plugin.setAttribute('headers', headers); + + plugin.setAttribute('background-color', this.getBackgroundColor()); + plugin.setAttribute('top-toolbar-height', this.getToolbarHeight()); + + const javascript = this.browserApi.getStreamInfo().javascript || 'block'; + plugin.setAttribute('javascript', javascript); + + if (this.browserApi.getStreamInfo().embedded) { + plugin.setAttribute( + 'top-level-url', this.browserApi.getStreamInfo().tabUrl); + } else { + plugin.toggleAttribute('full-frame', true); + } + + return plugin; + } + + /** @param {!BrowserApi} browserApi */ + init(browserApi) { + this.browserApi = browserApi; + this.originalUrl = this.browserApi.getStreamInfo().originalUrl; + + PDFMetrics.record(PDFMetrics.UserAction.DOCUMENT_OPENED); + + // Parse open pdf parameters. + this.paramsParser = new OpenPdfParamsParser( + destination => this.pluginController_.getNamedDestination(destination)); + + // Can only reload if we are in a normal tab. + if (chrome.tabs && this.browserApi.getStreamInfo().tabId !== -1) { + this.getErrorScreen().reloadFn = () => { + chrome.tabs.reload(this.browserApi.getStreamInfo().tabId); + }; + } + + // Create the viewport. + const defaultZoom = + this.browserApi.getZoomBehavior() === BrowserApi.ZoomBehavior.MANAGE ? + this.browserApi.getDefaultZoom() : + 1.0; + this.viewport_ = new Viewport( + window, this.getSizer(), this.getContent(), getScrollbarWidth(), + defaultZoom, this.getToolbarHeight()); + this.viewport_.setViewportChangedCallback(() => this.viewportChanged_()); + this.viewport_.setBeforeZoomCallback( + () => this.currentController.beforeZoom()); + this.viewport_.setAfterZoomCallback( + () => this.currentController.afterZoom()); + this.viewport_.setUserInitiatedCallback( + userInitiated => this.setUserInitiated_(userInitiated)); + window.addEventListener('beforeunload', () => this.resetTrackers_()); + + // Handle scripting messages from outside the extension that wish to + // interact with it. We also send a message indicating that extension has + // loaded and is ready to receive messages. + window.addEventListener('message', message => { + this.handleScriptingMessage(/** @type {!MessageObject} */ (message)); + }, false); + + // Create the plugin. + this.plugin_ = this.createPlugin_(); + this.getContent().appendChild(this.plugin_); + this.pluginController_ = new PluginController( + this.plugin_, this.viewport_, () => this.isUserInitiatedEvent, + () => this.loaded); + this.currentController = this.pluginController_; + this.tracker.add( + this.pluginController_.getEventTarget(), 'plugin-message', + e => this.handlePluginMessage(e)); + + document.body.addEventListener('change-page-and-xy', e => { + const point = this.viewport_.convertPageToScreen(e.detail.page, e.detail); + this.viewport_.goToPageAndXY(e.detail.page, point.x, point.y); + }); + + // Set up the ZoomManager. + this.zoomManager_ = ZoomManager.create( + this.browserApi.getZoomBehavior(), () => this.viewport_.getZoom(), + zoom => this.browserApi.setZoom(zoom), + this.browserApi.getInitialZoom()); + this.viewport_.setZoomManager(assert(this.zoomManager_)); + this.browserApi.addZoomEventListener( + zoom => this.zoomManager_.onBrowserZoomChange(zoom)); + + this.viewportScroller = + new ViewportScroller(this.viewport_, this.plugin_, window); + + // Request translated strings. + chrome.resourcesPrivate.getStrings( + chrome.resourcesPrivate.Component.PDF, + strings => this.handleStrings(strings)); + } + + /** + * Update the loading progress of the document in response to a progress + * message being received from the content controller. + * @param {number} progress the progress as a percentage. + */ + updateProgress(progress) { + if (progress === -1) { + // Document load failed. + this.getErrorScreen().show(); + this.getSizer().style.display = 'none'; + this.setLoadState(LoadState.FAILED); + this.sendDocumentLoadedMessage(); + } else if (progress === 100) { + // Document load complete. + if (this.lastViewportPosition) { + this.viewport_.position = this.lastViewportPosition; + } + this.paramsParser.getViewportFromUrlParams( + this.originalUrl, params => this.handleURLParams_(params)); + this.setLoadState(LoadState.SUCCESS); + this.sendDocumentLoadedMessage(); + while (this.delayedScriptingMessages_.length > 0) { + this.handleScriptingMessage(this.delayedScriptingMessages_.shift()); + } + } else { + this.setLoadState(LoadState.LOADING); + } + } + + /** @return {boolean} Whether the documentLoaded message can be sent. */ + readyToSendLoadMessage() { + return true; + } + + /** + * Sends a 'documentLoaded' message to the PDFScriptingAPI if the document has + * finished loading. + */ + sendDocumentLoadedMessage() { + if (this.loadState_ === LoadState.LOADING || + !this.readyToSendLoadMessage()) { + return; + } + this.sendScriptingMessage( + {type: 'documentLoaded', load_state: this.loadState_}); + } + + /** + * Called to update the UI before sending the viewport scripting message. + * Should be overridden by subclasses. + * @protected + */ + updateUIForViewportChange() {} + + /** + * A callback that's called after the viewport changes. + * @private + */ + viewportChanged_() { + if (!this.documentDimensions) { + return; + } + + this.updateUIForViewportChange(); + + const visiblePage = this.viewport_.getMostVisiblePage(); + const visiblePageDimensions = this.viewport_.getPageScreenRect(visiblePage); + const size = this.viewport_.size; + this.sendScriptingMessage({ + type: 'viewport', + pageX: visiblePageDimensions.x, + pageY: visiblePageDimensions.y, + pageWidth: visiblePageDimensions.width, + viewportWidth: size.width, + viewportHeight: size.height + }); + } + + /** + * Handle a scripting message from outside the extension (typically sent by + * PDFScriptingAPI in a page containing the extension) to interact with the + * plugin. + * @param {!MessageObject} message The message to handle. + */ + handleScriptingMessage(message) { + if (this.parentWindow_ !== message.source) { + this.parentWindow_ = message.source; + this.parentOrigin_ = message.origin; + // Ensure that we notify the embedder if the document is loaded. + if (this.loadState_ !== LoadState.LOADING) { + this.sendDocumentLoadedMessage(); + } + } + } + + /** + * @param {!MessageObject} message The message to handle. + * @return {boolean} Whether the message was delayed and added to the queue. + */ + delayScriptingMessage(message) { + // Delay scripting messages from users of the scripting API until the + // document is loaded. This simplifies use of the APIs. + if (this.loadState_ !== LoadState.SUCCESS) { + this.delayedScriptingMessages_.push(message); + return true; + } + return false; + } + + /** + * @param {!CustomEvent<MessageData>} e + * @protected + */ + handlePluginMessage(e) {} + + /** + * Sets document dimensions from the current controller. + * @param {!DocumentDimensionsMessageData} documentDimensions + * @protected + */ + setDocumentDimensions(documentDimensions) { + this.documentDimensions = documentDimensions; + this.isUserInitiatedEvent = false; + this.viewport_.setDocumentDimensions(this.documentDimensions); + this.isUserInitiatedEvent = true; + } + + /** + * @return {?Promise} Resolved when the load state reaches LOADED, + * rejects on FAILED. Returns null if no promise has been created, which + * is the case for initial load of the PDF. + */ + get loaded() { + return this.loaded_ ? this.loaded_.promise : null; + } + + /** @return {!Viewport} */ + get viewport() { + return assert(this.viewport_); + } + + /** + * @return {!PluginController} + * @protected + */ + get pluginController() { + return assert(this.pluginController_); + } + + /** + * Updates the load state and triggers completion of the `loaded` + * promise if necessary. + * @param {!LoadState} loadState + * @protected + */ + setLoadState(loadState) { + if (this.loadState_ === loadState) { + return; + } + assert( + loadState === LoadState.LOADING || + this.loadState_ === LoadState.LOADING); + this.loadState_ = loadState; + if (!this.initialLoadComplete_) { + this.initialLoadComplete_ = true; + return; + } + if (loadState === LoadState.SUCCESS) { + this.loaded_.resolve(); + } else if (loadState === LoadState.FAILED) { + this.loaded_.reject(); + } else { + this.loaded_ = new PromiseResolver(); + } + } + + /** + * Load a dictionary of translated strings into the UI. Used as a callback for + * chrome.resourcesPrivate. + * @param {?Object} strings Dictionary of translated strings + * @protected + */ + handleStrings(strings) { + if (!strings) { + return; + } + loadTimeData.data = strings; + + // Predefined zoom factors to be used when zooming in/out. These are in + // ascending order. + const presetZoomFactors = /** @type {!Array<number>} */ ( + JSON.parse(loadTimeData.getString('presetZoomFactors'))); + this.viewport_.setZoomFactorRange(presetZoomFactors); + + this.strings = strings; + + // Display the zoom toolbar after the UI text direction is set, to ensure it + // appears on the correct side of the PDF viewer. + this.getZoomToolbar().hidden = false; + } + + /** + * Handle open pdf parameters. This function updates the viewport as per + * the parameters mentioned in the url while opening pdf. The order is + * important as later actions can override the effects of previous actions. + * @param {Object} params The open params passed in the URL. + * @private + */ + handleURLParams_(params) { + if (params.zoom) { + this.viewport_.setZoom(params.zoom); + } + + if (params.position) { + this.viewport_.goToPageAndXY( + params.page ? params.page : 0, params.position.x, params.position.y); + } else if (params.page) { + this.viewport_.goToPage(params.page); + } + + if (params.view) { + this.isUserInitiatedEvent = false; + this.getZoomToolbar().forceFit(params.view); + if (params.viewPosition) { + const zoomedPositionShift = + params.viewPosition * this.viewport_.getZoom(); + const currentViewportPosition = this.viewport_.position; + if (params.view === FittingType.FIT_TO_WIDTH) { + currentViewportPosition.y += zoomedPositionShift; + } else if (params.view === FittingType.FIT_TO_HEIGHT) { + currentViewportPosition.x += zoomedPositionShift; + } + this.viewport_.position = currentViewportPosition; + } + this.isUserInitiatedEvent = true; + } + } + + /** + * A callback that sets |isUserInitiatedEvent| to |userInitiated|. + * @param {boolean} userInitiated The value to set |isUserInitiatedEvent| to. + * @private + */ + setUserInitiated_(userInitiated) { + assert(this.isUserInitiatedEvent !== userInitiated); + this.isUserInitiatedEvent = userInitiated; + } + + overrideSendScriptingMessageForTest() { + this.overrideSendScriptingMessageForTest_ = true; + } + + /** + * Send a scripting message outside the extension (typically to + * PDFScriptingAPI in a page containing the extension). + * @param {Object} message the message to send. + * @protected + */ + sendScriptingMessage(message) { + if (this.parentWindow_ && this.parentOrigin_) { + let targetOrigin; + // Only send data back to the embedder if it is from the same origin, + // unless we're sending it to ourselves (which could happen in the case + // of tests). We also allow documentLoaded messages through as this won't + // leak important information. + if (this.parentOrigin_ === window.location.origin) { + targetOrigin = this.parentOrigin_; + } else if (message.type === 'documentLoaded') { + targetOrigin = '*'; + } else { + targetOrigin = this.originalUrl; + } + try { + this.parentWindow_.postMessage(message, targetOrigin); + } catch (ok) { + // TODO(crbug.com/1004425): targetOrigin probably was rejected, such as + // a "data:" URL. This shouldn't cause this method to throw, though. + } + } + } + + /** + * Request to change the viewport fitting type. + * @param {!CustomEvent<FitToChangedEvent>} e + * @protected + */ + onFitToChanged(e) { + if (e.detail.fittingType === FittingType.FIT_TO_PAGE) { + this.viewport_.fitToPage(); + } else if (e.detail.fittingType === FittingType.FIT_TO_WIDTH) { + this.viewport_.fitToWidth(); + } else if (e.detail.fittingType === FittingType.FIT_TO_HEIGHT) { + this.viewport_.fitToHeight(); + } + + if (e.detail.userInitiated) { + PDFMetrics.recordFitTo(e.detail.fittingType); + } + } + + /** @protected */ + onZoomIn() { + this.viewport_.zoomIn(); + PDFMetrics.recordZoomAction(/*isZoomIn=*/ true); + } + + /** @protected */ + onZoomOut() { + this.viewport_.zoomOut(); + PDFMetrics.recordZoomAction(/*isZoomIn=*/ false); + } + + /** + * Handles a selected text reply from the current controller. + * @param {string} selectedText + * @protected + */ + handleSelectedTextReply(selectedText) { + const message = { + type: 'getSelectedTextReply', + selectedText: selectedText, + }; + if (this.overrideSendScriptingMessageForTest_) { + this.overrideSendScriptingMessageForTest_ = false; + try { + this.sendScriptingMessage(message); + } finally { + this.parentWindow_.postMessage('flush', '*'); + } + return; + } + this.sendScriptingMessage(message); + } + + /** @protected */ + rotateClockwise() { + PDFMetrics.record(PDFMetrics.UserAction.ROTATE); + this.viewport_.rotateClockwise(); + this.currentController.rotateClockwise(); + } + + /** @protected */ + rotateCounterclockwise() { + PDFMetrics.record(PDFMetrics.UserAction.ROTATE); + this.viewport_.rotateCounterclockwise(); + this.currentController.rotateCounterclockwise(); + } + + /** @private */ + resetTrackers_() { + this.viewport_.resetTracker(); + if (this.tracker) { + this.tracker.removeAll(); + } + } +} + +customElements.define(PDFViewerBaseElement.is, PDFViewerBaseElement); diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer_pp.html b/chromium/chrome/browser/resources/pdf/pdf_viewer_pp.html new file mode 100644 index 00000000000..dac20fda069 --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer_pp.html @@ -0,0 +1,21 @@ +<style include="pdf-viewer-shared-style"> + viewer-page-indicator { + opacity: 0; + visibility: hidden; + z-index: 2; + } +</style> + +<div id="sizer"></div> + +<viewer-zoom-toolbar id="zoom-toolbar" strings="[[strings]]" + on-fit-to-changed="onFitToChanged" is-print-preview + on-zoom-in="onZoomIn" on-zoom-out="onZoomOut" + hidden> +</viewer-zoom-toolbar> + +<viewer-error-screen id="error-screen"></viewer-error-screen> + +<viewer-page-indicator id="page-indicator"></viewer-page-indicator> + +<div id="content"></div> diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer_pp.js b/chromium/chrome/browser/resources/pdf/pdf_viewer_pp.js new file mode 100644 index 00000000000..6fa9a6f3e3c --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer_pp.js @@ -0,0 +1,379 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import './elements/viewer-error-screen.js'; +import './elements/viewer-page-indicator.js'; +import './elements/shared-vars.js'; +import './pdf_viewer_shared_style.js'; + +import {assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {isRTL} from 'chrome://resources/js/util.m.js'; +import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {BrowserApi} from './browser_api.js'; +import {FittingType} from './constants.js'; +import {MessageData, PrintPreviewParams} from './controller.js'; +import {DeserializeKeyEvent, LoadState, SerializeKeyEvent} from './pdf_scripting_api.js'; +import {PDFViewerBaseElement} from './pdf_viewer_base.js'; +import {DestinationMessageData, DocumentDimensionsMessageData, MessageObject, shouldIgnoreKeyEvents} from './pdf_viewer_utils.js'; +import {ToolbarManager} from './toolbar_manager.js'; + +class PDFViewerPPElement extends PDFViewerBaseElement { + static get is() { + return 'pdf-viewer-pp'; + } + + static get template() { + return html`{__html_template__}`; + } + + constructor() { + super(); + + /** @private {boolean} */ + this.isPrintPreviewLoadingFinished_ = false; + + /** @private {boolean} */ + this.inPrintPreviewMode_ = false; + + /** @private {boolean} */ + this.dark_ = false; + + /** @private {?ToolbarManager} */ + this.toolbarManager_ = null; + } + + /** @override */ + getContent() { + return /** @type {!HTMLDivElement} */ (this.$$('#content')); + } + + /** @override */ + getSizer() { + return /** @type {!HTMLDivElement} */ (this.$$('#sizer')); + } + + /** @override */ + getZoomToolbar() { + return /** @type {!ViewerZoomToolbarElement} */ (this.$$('#zoom-toolbar')); + } + + /** @override */ + getErrorScreen() { + return /** @type {!ViewerErrorScreenElement} */ (this.$$('#error-screen')); + } + + /** @override */ + getBackgroundColor() { + return PRINT_PREVIEW_BACKGROUND_COLOR; + } + + /** @param {!BrowserApi} browserApi */ + init(browserApi) { + super.init(browserApi); + + this.toolbarManager_ = + new ToolbarManager(window, null, this.getZoomToolbar()); + + // Setup the keyboard event listener. + document.addEventListener( + 'keydown', + e => this.handleKeyEvent_(/** @type {!KeyboardEvent} */ (e))); + } + + /** + * Handle key events. These may come from the user directly or via the + * scripting API. + * @param {!KeyboardEvent} e the event to handle. + * @private + */ + handleKeyEvent_(e) { + if (shouldIgnoreKeyEvents(document.activeElement) || e.defaultPrevented) { + return; + } + + this.toolbarManager_.hideToolbarsAfterTimeout(); + // Let the viewport handle directional key events. + if (this.viewport.handleDirectionalKeyEvent(e, false)) { + return; + } + + switch (e.key) { + case 'Tab': + this.toolbarManager_.showToolbarsForKeyboardNavigation(); + return; + case 'Escape': + break; // Ensure escape falls through to the print-preview handler. + case 'a': + if (e.ctrlKey || e.metaKey) { + this.pluginController.selectAll(); + // Since we do selection ourselves. + e.preventDefault(); + } + return; + case '[': + if (e.ctrlKey) { + this.rotateCounterclockwise(); + } + return; + case '\\': + if (e.ctrlKey) { + this.getZoomToolbar().fitToggleFromHotKey(); + } + return; + case ']': + if (e.ctrlKey) { + this.rotateClockwise(); + } + return; + } + + // Give print preview a chance to handle the key event. + if (!e.fromScriptingAPI) { + this.sendScriptingMessage( + {type: 'sendKeyEvent', keyEvent: SerializeKeyEvent(e)}); + } else { + // Show toolbars as a fallback. + if (!(e.shiftKey || e.ctrlKey || e.altKey)) { + this.toolbarManager_.showToolbars(); + } + } + } + + /** @private */ + sendBackgroundColorForPrintPreview_() { + this.pluginController.backgroundColorChanged( + this.dark_ ? PRINT_PREVIEW_DARK_BACKGROUND_COLOR : + PRINT_PREVIEW_BACKGROUND_COLOR); + } + + /** @override */ + updateUIForViewportChange() { + // Offset the toolbar position so that it doesn't move if scrollbars appear. + const hasScrollbars = this.viewport.documentHasScrollbars(); + const scrollbarWidth = this.viewport.scrollbarWidth; + const verticalScrollbarWidth = hasScrollbars.vertical ? scrollbarWidth : 0; + const horizontalScrollbarWidth = + hasScrollbars.horizontal ? scrollbarWidth : 0; + + // Shift the zoom toolbar to the left by half a scrollbar width. This + // gives a compromise: if there is no scrollbar visible then the toolbar + // will be half a scrollbar width further left than the spec but if there + // is a scrollbar visible it will be half a scrollbar width further right + // than the spec. In LTR layout, the zoom toolbar is on the left + // left side, but the scrollbar is still on the right, so this is not + // necessary. + const zoomToolbar = this.getZoomToolbar(); + if (isRTL()) { + zoomToolbar.style.right = + -verticalScrollbarWidth + (scrollbarWidth / 2) + 'px'; + } + // Having a horizontal scrollbar is much rarer so we don't offset the + // toolbar from the bottom any more than what the spec says. This means + // that when there is a scrollbar visible, it will be a full scrollbar + // width closer to the bottom of the screen than usual, but this is ok. + zoomToolbar.style.bottom = -horizontalScrollbarWidth + 'px'; + + // Update the page indicator. + const visiblePage = this.viewport.getMostVisiblePage(); + const pageIndicator = this.$$('#page-indicator'); + const lastIndex = pageIndicator.index; + pageIndicator.index = visiblePage; + if (this.documentDimensions.pageDimensions.length > 1 && + hasScrollbars.vertical && lastIndex !== undefined) { + pageIndicator.style.visibility = 'visible'; + } else { + pageIndicator.style.visibility = 'hidden'; + } + + this.pluginController.viewportChanged(); + } + + /** @override */ + handleScriptingMessage(message) { + super.handleScriptingMessage(message); + + if (this.handlePrintPreviewScriptingMessage_(message)) { + return; + } + + if (this.delayScriptingMessage(message)) { + return; + } + + switch (message.data.type.toString()) { + case 'getSelectedText': + this.pluginController.getSelectedText(); + break; + case 'selectAll': + this.pluginController.selectAll(); + break; + } + } + + /** + * Handle scripting messages specific to print preview. + * @param {!MessageObject} message the message to handle. + * @return {boolean} true if the message was handled, false otherwise. + * @private + */ + handlePrintPreviewScriptingMessage_(message) { + let messageData = message.data; + switch (messageData.type.toString()) { + case 'loadPreviewPage': + messageData = + /** @type {{ url: string, index: number }} */ (messageData); + this.pluginController.loadPreviewPage( + messageData.url, messageData.index); + return true; + case 'resetPrintPreviewMode': + messageData = /** @type {!PrintPreviewParams} */ (messageData); + this.setLoadState(LoadState.LOADING); + if (!this.inPrintPreviewMode_) { + this.inPrintPreviewMode_ = true; + this.isUserInitiatedEvent = false; + this.getZoomToolbar().forceFit(FittingType.FIT_TO_PAGE); + this.isUserInitiatedEvent = true; + } + + // Stash the scroll location so that it can be restored when the new + // document is loaded. + this.lastViewportPosition = this.viewport.position; + this.$$('#page-indicator').pageLabels = messageData.pageNumbers; + + this.pluginController.resetPrintPreviewMode(messageData); + return true; + case 'sendKeyEvent': + this.handleKeyEvent_(/** @type {!KeyboardEvent} */ (DeserializeKeyEvent( + /** @type {{ keyEvent: Object }} */ (message.data).keyEvent))); + return true; + case 'hideToolbars': + this.toolbarManager_.resetKeyboardNavigationAndHideToolbars(); + return true; + case 'darkModeChanged': + this.dark_ = /** @type {{darkMode: boolean}} */ (message.data).darkMode; + this.sendBackgroundColorForPrintPreview_(); + return true; + case 'scrollPosition': + const position = this.viewport.position; + messageData = /** @type {{ x: number, y: number }} */ (message.data); + position.y += messageData.y; + position.x += messageData.x; + this.viewport.position = position; + return true; + } + + return false; + } + + /** @override */ + setLoadState(loadState) { + super.setLoadState(loadState); + if (loadState === LoadState.FAILED) { + this.isPrintPreviewLoadingFinished_ = true; + } + } + + /** @override */ + handlePluginMessage(e) { + const data = e.detail; + switch (data.type.toString()) { + case 'documentDimensions': + this.setDocumentDimensions( + /** @type {!DocumentDimensionsMessageData} */ (data)); + return; + case 'getSelectedTextReply': + this.handleSelectedTextReply( + /** @type {{ selectedText: string }} */ (data).selectedText); + return; + case 'loadProgress': + this.updateProgress( + /** @type {{ progress: number }} */ (data).progress); + return; + case 'navigateToDestination': + const destinationData = /** @type {!DestinationMessageData} */ (data); + this.viewport.handleNavigateToDestination( + destinationData.page, destinationData.x, destinationData.y, + destinationData.zoom); + return; + case 'printPreviewLoaded': + this.handlePrintPreviewLoaded_(); + return; + case 'setIsSelecting': + this.viewportScroller.setEnableScrolling( + /** @type {{ isSelecting: boolean }} */ (data).isSelecting); + return; + case 'getNamedDestinationReply': + this.paramsParser.onNamedDestinationReceived( + /** @type {{ pageNumber: number }} */ (data).pageNumber); + return; + case 'touchSelectionOccurred': + this.sendScriptingMessage({ + type: 'touchSelectionOccurred', + }); + return; + case 'documentFocusChanged': + // TODO(crbug.com/1069370): Draw a focus rect around plugin. + return; + case 'beep': + case 'formFocusChange': + case 'getPassword': + case 'metadata': + case 'navigate': + case 'setIsEditing': + // These messages are not relevant in Print Preview. + return; + } + assertNotReached('Unknown message type received: ' + data.type); + } + + /** + * Handles a notification that print preview has loaded from the + * current controller. + * @private + */ + handlePrintPreviewLoaded_() { + this.isPrintPreviewLoadingFinished_ = true; + this.sendDocumentLoadedMessage(); + } + + /** @override */ + readyToSendLoadMessage() { + return this.isPrintPreviewLoadingFinished_; + } + + /** @override */ + handleStrings(strings) { + super.handleStrings(strings); + + if (!strings) { + return; + } + this.sendBackgroundColorForPrintPreview_(); + } + + /** @override */ + updateProgress(progress) { + super.updateProgress(progress); + if (progress === 100) { + this.toolbarManager_.hideToolbarsAfterTimeout(); + } + } +} + +/** + * The background color used for print preview (--google-grey-refresh-300). + * @type {string} + */ +const PRINT_PREVIEW_BACKGROUND_COLOR = '0xFFDADCE0'; + +/** + * The background color used for print preview when dark mode is enabled + * (--google-grey-refresh-700). + * @type {string} + */ +const PRINT_PREVIEW_DARK_BACKGROUND_COLOR = '0xFF5F6368'; + +customElements.define(PDFViewerPPElement.is, PDFViewerPPElement); diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer_shared_style.html b/chromium/chrome/browser/resources/pdf/pdf_viewer_shared_style.html new file mode 100644 index 00000000000..ba2a5e4cf9b --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer_shared_style.html @@ -0,0 +1,33 @@ +<template> + <style> + #content { + height: 100%; + position: fixed; + width: 100%; + z-index: 1; + } + + #plugin { + height: 100%; + position: absolute; + width: 100%; + } + + #sizer { + position: absolute; + z-index: 0; + } + + @media(max-height: 200px) { + viewer-zoom-toolbar { + display: none; + } + } + + @media(max-width: 300px) { + viewer-zoom-toolbar { + display: none; + } + } + </style> +</template> diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer_shared_style.js b/chromium/chrome/browser/resources/pdf/pdf_viewer_shared_style.js new file mode 100644 index 00000000000..d7411e11a3a --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer_shared_style.js @@ -0,0 +1,11 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +const template = document.createElement('template'); +template.innerHTML = ` +<dom-module id="pdf-viewer-shared-style">{__html_template__}</dom-module> +`; +document.body.appendChild(template.content.cloneNode(true)); diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer_utils.js b/chromium/chrome/browser/resources/pdf/pdf_viewer_utils.js new file mode 100644 index 00000000000..2250aa80637 --- /dev/null +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer_utils.js @@ -0,0 +1,64 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {MessageData} from './controller.js'; +import {LayoutOptions} from './viewport.js'; + +/** + * @typedef {{ + * source: Object, + * origin: string, + * data: !MessageData, + * }} + */ +export let MessageObject; + +/** + * @typedef {{ + * type: string, + * height: number, + * width: number, + * layoutOptions: (!LayoutOptions|undefined), + * pageDimensions: Array + * }} + */ +export let DocumentDimensionsMessageData; + +/** + * @typedef {{ + * type: string, + * page: number, + * x: number, + * y: number, + * zoom: number + * }} + */ +export let DestinationMessageData; + +/** + * @typedef {{ + * hasUnsavedChanges: (boolean|undefined), + * fileName: string, + * dataToSave: !ArrayBuffer + * }} + */ +export let RequiredSaveResult; + +/** + * Whether keydown events should currently be ignored. Events are ignored when + * an editable element has focus, to allow for proper editing controls. + * @param {Element} activeElement The currently selected DOM node. + * @return {boolean} True if keydown events should be ignored. + */ +export function shouldIgnoreKeyEvents(activeElement) { + while (activeElement.shadowRoot != null && + activeElement.shadowRoot.activeElement != null) { + activeElement = activeElement.shadowRoot.activeElement; + } + + return ( + activeElement.isContentEditable || + (activeElement.tagName === 'INPUT' && activeElement.type !== 'radio') || + activeElement.tagName === 'TEXTAREA'); +} diff --git a/chromium/chrome/browser/resources/pdf/toolbar_manager.js b/chromium/chrome/browser/resources/pdf/toolbar_manager.js index 847b21172fc..f4b7aade0b4 100644 --- a/chromium/chrome/browser/resources/pdf/toolbar_manager.js +++ b/chromium/chrome/browser/resources/pdf/toolbar_manager.js @@ -4,20 +4,42 @@ import {isRTL} from 'chrome://resources/js/util.m.js'; -/** Idle time in ms before the UI is hidden. */ +/** + * Idle time in ms before the UI is hidden. + * @type {number} + */ const HIDE_TIMEOUT = 2000; -/** Time in ms after force hide before toolbar is shown again. */ + +/** + * Time in ms after force hide before toolbar is shown again. + * @type {number} + */ const FORCE_HIDE_TIMEOUT = 1000; + /** * Velocity required in a mousemove to reveal the UI (pixels/ms). This is * intended to be high enough that a fast flick of the mouse is required to * reach it. + * @type {number} */ const SHOW_VELOCITY = 10; -/** Distance from the top of the screen required to reveal the toolbars. */ + +/** + * Distance from the top of the screen required to reveal the toolbars. + * @type {number} + */ const TOP_TOOLBAR_REVEAL_DISTANCE = 100; -/** Distance from the bottom-right of the screen required to reveal toolbars. */ + +/** + * Distance from right of the screen required to reveal toolbars. + * @type {number} + */ const SIDE_TOOLBAR_REVEAL_DISTANCE_RIGHT = 150; + +/** + * Distance from bottom of the screen required to reveal toolbars. + * @type {number} + */ const SIDE_TOOLBAR_REVEAL_DISTANCE_BOTTOM = 250; /** @@ -45,7 +67,7 @@ function isMouseNearSideToolbar(e, window, reverse) { return atSide && atBottom; } -/** Responsible for co-ordinating between multiple toolbar elements. */ +// Responsible for co-ordinating between multiple toolbar elements. export class ToolbarManager { /** * @param {!Window} window The window containing the UI. @@ -89,6 +111,12 @@ export class ToolbarManager { this.window_.addEventListener('resize', this.resizeDropdowns_.bind(this)); this.resizeDropdowns_(); + document.addEventListener( + 'mousemove', + e => this.handleMouseMove_(/** @type {!MouseEvent} */ (e))); + document.addEventListener( + 'mouseout', () => this.hideToolbarsForMouseOut_()); + if (this.isPrintPreview_) { this.zoomToolbar_.addEventListener('keyboard-navigation-active', e => { this.keyboardNavigationActive = e.detail; @@ -96,8 +124,11 @@ export class ToolbarManager { } } - /** @param {!MouseEvent} e */ - handleMouseMove(e) { + /** + * @param {!MouseEvent} e + * @private + */ + handleMouseMove_(e) { this.isMouseNearTopToolbar_ = !!this.toolbar_ && isMouseNearTopToolbar(e); this.isMouseNearSideToolbar_ = isMouseNearSideToolbar(e, this.window_, this.isPrintPreview_); @@ -192,8 +223,9 @@ export class ToolbarManager { /** * Hide toolbars after a delay, regardless of the position of the mouse. * Intended to be called when the mouse has moved out of the parent window. + * @private */ - hideToolbarsForMouseOut() { + hideToolbarsForMouseOut_() { this.isMouseNearTopToolbar_ = false; this.isMouseNearSideToolbar_ = false; this.hideToolbarsAfterTimeout(); diff --git a/chromium/chrome/browser/resources/pdf/viewport.js b/chromium/chrome/browser/resources/pdf/viewport.js index 37967176729..3e68d39f673 100644 --- a/chromium/chrome/browser/resources/pdf/viewport.js +++ b/chromium/chrome/browser/resources/pdf/viewport.js @@ -4,9 +4,10 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; -import {$} from 'chrome://resources/js/util.m.js'; +import {$, hasKeyModifiers} from 'chrome://resources/js/util.m.js'; import {FittingType} from './constants.js'; +import {GestureDetector, PinchEventDetail} from './gesture_detector.js'; import {InactiveZoomManager, ZoomManager} from './zoom_manager.js'; /** @@ -66,35 +67,29 @@ function vectorDelta(p1, p2) { return {x: p2.x - p1.x, y: p2.y - p1.y}; } -/** - * @param {!Point} coordinateInFrame - * @return {!Point} Coordinate converted to plugin coordinates. - */ -function frameToPluginCoordinate(coordinateInFrame) { - const container = $('plugin'); - return { - x: coordinateInFrame.x - container.getBoundingClientRect().left, - y: coordinateInFrame.y - container.getBoundingClientRect().top - }; -} - export class Viewport { /** * @param {!Window} window * @param {!HTMLDivElement} sizer The element which represents the size of the * document in the viewport + * @param {!HTMLDivElement} content The element which is the parent of the + * plugin in the viewer. * @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 * be left blank above the document for the toolbar. */ - constructor(window, sizer, scrollbarWidth, defaultZoom, topToolbarHeight) { + constructor( + window, sizer, content, scrollbarWidth, defaultZoom, topToolbarHeight) { /** @private {!Window} */ this.window_ = window; /** @private {!HTMLDivElement} */ this.sizer_ = sizer; + /** @private {!HTMLDivElement} */ + this.content_ = content; + /** @private {number} */ this.scrollbarWidth_ = scrollbarWidth; @@ -168,11 +163,33 @@ export class Viewport { /** @private {!EventTracker} */ this.tracker_ = new EventTracker(); + /** @private {!GestureDetector} */ + this.gestureDetector_ = new GestureDetector(this.content_); + + /** @private {boolean} */ + this.sentPinchEvent_ = false; + + this.gestureDetector_.getEventTarget().addEventListener( + 'pinchstart', + e => this.onPinchStart_( + /** @type {!CustomEvent<!PinchEventDetail>} */ (e))); + this.gestureDetector_.getEventTarget().addEventListener( + 'pinchupdate', + e => this.onPinchUpdate_( + /** @type {!CustomEvent<!PinchEventDetail>} */ (e))); + this.gestureDetector_.getEventTarget().addEventListener( + 'pinchend', + e => this.onPinchEnd_( + /** @type {!CustomEvent<!PinchEventDetail>} */ (e))); + // Set to a default zoom manager - used in tests. this.setZoomManager(new InactiveZoomManager(this.getZoom.bind(this), 1)); window.addEventListener('scroll', this.updateViewport_.bind(this)); window.addEventListener('resize', this.resizeWrapper_.bind(this)); + + document.body.addEventListener( + 'change-zoom', e => this.setZoom(e.detail.zoom)); } /** @param {function():void} viewportChangedCallback */ @@ -288,8 +305,8 @@ export class Viewport { y: point.y * pointsToPixels, }); return { - x: result.x + Viewport.PAGE_SHADOW.left, - y: result.y + Viewport.PAGE_SHADOW.top, + x: result.x + PAGE_SHADOW.left, + y: result.y + PAGE_SHADOW.top, }; } @@ -348,9 +365,9 @@ export class Viewport { * @param {number} zoom Zoom to compute scrollbars for * @return {{horizontal: boolean, vertical: boolean}} Whether horizontal or * vertical scrollbars are needed. - * @private + * Public so tests can call it directly. */ - documentNeedsScrollbars_(zoom) { + documentNeedsScrollbars(zoom) { const zoomedDimensions = this.getZoomedDocumentDimensions_(zoom); if (!zoomedDimensions) { return {horizontal: false, vertical: false}; @@ -376,7 +393,7 @@ export class Viewport { * vertical scrollbars are needed. */ documentHasScrollbars() { - return this.documentNeedsScrollbars_(this.getZoom()); + return this.documentNeedsScrollbars(this.getZoom()); } /** @@ -394,6 +411,19 @@ export class Viewport { } /** + * @param {!Point} coordinateInFrame + * @return {!Point} Coordinate converted to plugin coordinates. + * @private + */ + frameToPluginCoordinate_(coordinateInFrame) { + const container = this.content_.querySelector('#plugin'); + return { + x: coordinateInFrame.x - container.getBoundingClientRect().left, + y: coordinateInFrame.y - container.getBoundingClientRect().top + }; + } + + /** * Called when the viewport should be updated. * @private */ @@ -447,7 +477,7 @@ export class Viewport { /** @return {!Size} the size of the viewport excluding scrollbars. */ get size() { - const needsScrollbars = this.documentNeedsScrollbars_(this.getZoom()); + const needsScrollbars = this.documentNeedsScrollbars(this.getZoom()); const scrollbarWidth = needsScrollbars.vertical ? this.scrollbarWidth_ : 0; const scrollbarHeight = needsScrollbars.horizontal ? this.scrollbarWidth_ : 0; @@ -589,9 +619,7 @@ export class Viewport { }; } - /** - * @param {number} newZoom The zoom level to zoom to. - */ + /** @param {number} newZoom The zoom level to zoom to. */ setZoom(newZoom) { this.fittingType_ = FittingType.NONE; this.mightZoom_(() => { @@ -775,7 +803,7 @@ export class Viewport { pageDimensions.width, pageDimensions.height); // Check if there needs to be any scrollbars. - const needsScrollbars = this.documentNeedsScrollbars_(zoom); + const needsScrollbars = this.documentNeedsScrollbars(zoom); // If the document fits, just return the zoom. if (!needsScrollbars.horizontal && !needsScrollbars.vertical) { @@ -992,84 +1020,152 @@ export class Viewport { } /** - * Pinch zoom event handler. - * @param {!Object} e The pinch event. + * @param {!KeyboardEvent} e + * @private */ - pinchZoom(e) { - this.mightZoom_(() => { - this.pinchPhase_ = e.direction === 'out' ? - Viewport.PinchPhase.PINCH_UPDATE_ZOOM_OUT : - Viewport.PinchPhase.PINCH_UPDATE_ZOOM_IN; - - const scaleDelta = e.startScaleRatio / this.prevScale_; - if (this.firstPinchCenterInFrame_ != null) { - this.pinchPanVector_ = - vectorDelta(e.center, this.firstPinchCenterInFrame_); - } + pageUpHandler_(e) { + // Go to the previous page if we are fit-to-page or fit-to-height. + if (this.isPagedMode_()) { + this.goToPreviousPage(); + // Since we do the movement of the page. + e.preventDefault(); + } else if ( + /** @type {!{fromScriptingAPI: (boolean|undefined)}} */ (e) + .fromScriptingAPI) { + this.position.y -= this.size.height; + } + } - const needsScrollbars = - this.documentNeedsScrollbars_(this.zoomManager_.applyBrowserZoom( - this.clampZoom_(this.internalZoom_ * scaleDelta))); - - this.pinchCenter_ = e.center; - - // If there's no horizontal scrolling, keep the content centered so the - // user can't zoom in on the non-content area. - // TODO(mcnee) Investigate other ways of scaling when we don't have - // horizontal scrolling. We want to keep the document centered, - // but this causes a potentially awkward transition when we start - // using the gesture center. - if (!needsScrollbars.horizontal) { - this.pinchCenter_ = { - x: this.window_.innerWidth / 2, - y: this.window_.innerHeight / 2 - }; - } else if (this.keepContentCentered_) { - this.oldCenterInContent_ = - this.frameToContent_(frameToPluginCoordinate(e.center)); - this.keepContentCentered_ = false; - } + /** + * @param {!KeyboardEvent} e + * @private + */ + pageDownHandler_(e) { + // Go to the next page if we are fit-to-page or fit-to-height. + if (this.isPagedMode_()) { + this.goToNextPage(); + // Since we do the movement of the page. + e.preventDefault(); + } else if ( + /** @type {!{fromScriptingAPI: (boolean|undefined)}} */ (e) + .fromScriptingAPI) { + this.position.y += this.size.height; + } + } - this.setPinchZoomInternal_(scaleDelta, frameToPluginCoordinate(e.center)); - this.updateViewport_(); - this.prevScale_ = e.startScaleRatio; - }); + /** + * @param {!KeyboardEvent} e + * @param {boolean} formFieldFocused + * @private + */ + arrowLeftHandler_(e, formFieldFocused) { + if (hasKeyModifiers(e)) { + return; + } + + // Go to the previous page if there are no horizontal scrollbars and + // no form field is focused. + if (!(this.documentHasScrollbars().horizontal || formFieldFocused)) { + this.goToPreviousPage(); + // Since we do the movement of the page. + e.preventDefault(); + } else if ( + /** @type {!{fromScriptingAPI: (boolean|undefined)}} */ (e) + .fromScriptingAPI) { + this.position.x -= SCROLL_INCREMENT; + } } - /** @param {!Object} e The pinch event. */ - pinchZoomStart(e) { - this.pinchPhase_ = Viewport.PinchPhase.PINCH_START; - this.prevScale_ = 1; - this.oldCenterInContent_ = - this.frameToContent_(frameToPluginCoordinate(e.center)); + /** + * @param {!KeyboardEvent} e + * @param {boolean} formFieldFocused + * @private + */ + arrowRightHandler_(e, formFieldFocused) { + if (hasKeyModifiers(e)) { + return; + } - const needsScrollbars = this.documentNeedsScrollbars_(this.getZoom()); - this.keepContentCentered_ = !needsScrollbars.horizontal; - // We keep track of begining of the pinch. - // By doing so we will be able to compute the pan distance. - this.firstPinchCenterInFrame_ = e.center; + // Go to the next page if there are no horizontal scrollbars and no + // form field is focused. + if (!(this.documentHasScrollbars().horizontal || formFieldFocused)) { + this.goToNextPage(); + // Since we do the movement of the page. + e.preventDefault(); + } else if ( + /** @type {!{fromScriptingAPI: (boolean|undefined)}} */ (e) + .fromScriptingAPI) { + this.position.x += SCROLL_INCREMENT; + } } - /** @param {!Object} e The pinch event. */ - pinchZoomEnd(e) { - this.mightZoom_(() => { - this.pinchPhase_ = Viewport.PinchPhase.PINCH_END; - const scaleDelta = e.startScaleRatio / this.prevScale_; - this.pinchCenter_ = /** @type {!Point} */ (e.center); + /** + * @param {boolean} fromScriptingAPI + * @private + */ + arrowDownHandler_(fromScriptingAPI) { + if (fromScriptingAPI) { + this.position.y += SCROLL_INCREMENT; + } + } - this.setPinchZoomInternal_(scaleDelta, frameToPluginCoordinate(e.center)); - this.updateViewport_(); - }); + /** + * @param {boolean} fromScriptingAPI + * @private + */ + arrowUpHandler_(fromScriptingAPI) { + if (fromScriptingAPI) { + this.position.y -= SCROLL_INCREMENT; + } + } - this.pinchPhase_ = Viewport.PinchPhase.PINCH_NONE; - this.pinchPanVector_ = null; - this.pinchCenter_ = null; - this.firstPinchCenterInFrame_ = null; + /** + * Handle certain directional key events. + * @param {!KeyboardEvent} e the event to handle. + * @param {boolean} formFieldFocused Whether a form field is currently + * focused. + * @return {boolean} Whether the event was handled. + */ + handleDirectionalKeyEvent(e, formFieldFocused) { + // Certain scroll events may be sent from outside of the extension. + const fromScriptingAPI = + /** @type {!{fromScriptingAPI: (boolean|undefined)}} */ (e) + .fromScriptingAPI; + + switch (e.key) { + case '': + if (e.shiftKey) { + this.pageUpHandler_(e); + } else { + this.pageDownHandler_(e); + } + return true; + case 'PageUp': + this.pageUpHandler_(e); + return true; + case 'PageDown': + this.pageDownHandler_(e); + return true; + case 'ArrowLeft': + this.arrowLeftHandler_(e, formFieldFocused); + return true; + case 'ArrowUp': + this.arrowUpHandler_(!!fromScriptingAPI); + return true; + case 'ArrowRight': + this.arrowRightHandler_(e, formFieldFocused); + return true; + case 'ArrowDown': + this.arrowDownHandler_(!!fromScriptingAPI); + return true; + default: + return false; + } } /** * Go to the next page. If the document is in two-up view, go to the left page - * of the next row. + * of the next row. Public for tests. */ goToNextPage() { const currentPage = this.getMostVisiblePage(); @@ -1080,7 +1176,7 @@ export class Viewport { /** * Go to the previous page. If the document is in two-up view, go to the left - * page of the previous row. + * page of the previous row. Public for tests. */ goToPreviousPage() { const currentPage = this.getMostVisiblePage(); @@ -1123,7 +1219,7 @@ export class Viewport { // Unless we're in fit to page or fit to height mode, scroll above the // page by |this.topToolbarHeight_| so that the toolbar isn't covering it // initially. - if (!this.isPagedMode()) { + if (!this.isPagedMode_()) { toolbarOffset = this.topToolbarHeight_; } this.position = { @@ -1160,7 +1256,7 @@ export class Viewport { */ getPageInsetDimensions(page) { const pageDimensions = this.pageDimensions_[page]; - const shadow = Viewport.PAGE_SHADOW; + const shadow = PAGE_SHADOW; return { x: pageDimensions.x + shadow.left, y: pageDimensions.y + shadow.top, @@ -1192,7 +1288,7 @@ export class Viewport { // TODO(raymes): This should really be set when the PDF plugin passes the // page coordinates, but it isn't yet. const x = (this.documentDimensions_.width - pageDimensions.width) / 2 + - Viewport.PAGE_SHADOW.left; + PAGE_SHADOW.left; // Compute the space on the left of the document if the document fits // completely in the screen. const zoom = this.getZoom(); @@ -1213,14 +1309,34 @@ export class Viewport { * In a paged mode, page up and page down scroll to the top of the * previous/next page and part of the page is under the toolbar. * @return {boolean} Whether the current fitting type is a paged mode. + * @private */ - isPagedMode() { + isPagedMode_() { return ( this.fittingType_ === FittingType.FIT_TO_PAGE || this.fittingType_ === FittingType.FIT_TO_HEIGHT); } /** + * Handles a navigation request to a destination from the current controller. + * @param {number} page + * @param {number} x + * @param {number} y + * @param {number} zoom + */ + handleNavigateToDestination(page, x, y, zoom) { + if (zoom) { + this.setZoom(zoom); + } + + if (x || y) { + this.goToPageAndXY(page, x ? x : 0, y ? y : 0); + } else { + this.goToPage(page); + } + } + + /** * @param {!PartialPoint} point The position to which to scroll the viewport. */ scrollTo(point) { @@ -1254,6 +1370,112 @@ export class Viewport { this.tracker_.removeAll(); } } + + /** + * A callback that's called when an update to a pinch zoom is detected. + * @param {!CustomEvent<!PinchEventDetail>} e the pinch event. + * @private + */ + onPinchUpdate_(e) { + // Throttle number of pinch events to one per frame. + if (this.sentPinchEvent_) { + return; + } + + this.sentPinchEvent_ = true; + this.window_.requestAnimationFrame(() => { + this.sentPinchEvent_ = false; + this.mightZoom_(() => { + const {direction, center, startScaleRatio} = e.detail; + this.pinchPhase_ = direction === 'out' ? + Viewport.PinchPhase.PINCH_UPDATE_ZOOM_OUT : + Viewport.PinchPhase.PINCH_UPDATE_ZOOM_IN; + + const scaleDelta = startScaleRatio / this.prevScale_; + if (this.firstPinchCenterInFrame_ != null) { + this.pinchPanVector_ = + vectorDelta(center, this.firstPinchCenterInFrame_); + } + + const needsScrollbars = + this.documentNeedsScrollbars(this.zoomManager_.applyBrowserZoom( + this.clampZoom_(this.internalZoom_ * scaleDelta))); + + this.pinchCenter_ = center; + + // If there's no horizontal scrolling, keep the content centered so + // the user can't zoom in on the non-content area. + // TODO(mcnee) Investigate other ways of scaling when we don't have + // horizontal scrolling. We want to keep the document centered, + // but this causes a potentially awkward transition when we start + // using the gesture center. + if (!needsScrollbars.horizontal) { + this.pinchCenter_ = { + x: this.window_.innerWidth / 2, + y: this.window_.innerHeight / 2 + }; + } else if (this.keepContentCentered_) { + this.oldCenterInContent_ = + this.frameToContent_(this.frameToPluginCoordinate_(center)); + this.keepContentCentered_ = false; + } + + this.setPinchZoomInternal_( + scaleDelta, this.frameToPluginCoordinate_(center)); + this.updateViewport_(); + this.prevScale_ = /** @type {number} */ (startScaleRatio); + }); + }); + } + + /** + * A callback that's called when the end of a pinch zoom is detected. + * @param {!CustomEvent<!PinchEventDetail>} e the pinch event. + * @private + */ + onPinchEnd_(e) { + // Using rAF for pinch end prevents pinch updates scheduled by rAF getting + // sent after the pinch end. + this.window_.requestAnimationFrame(() => { + this.mightZoom_(() => { + const {center, startScaleRatio} = e.detail; + this.pinchPhase_ = Viewport.PinchPhase.PINCH_END; + const scaleDelta = startScaleRatio / this.prevScale_; + this.pinchCenter_ = /** @type {!Point} */ (center); + + this.setPinchZoomInternal_( + scaleDelta, this.frameToPluginCoordinate_(center)); + this.updateViewport_(); + }); + + this.pinchPhase_ = Viewport.PinchPhase.PINCH_NONE; + this.pinchPanVector_ = null; + this.pinchCenter_ = null; + this.firstPinchCenterInFrame_ = null; + }); + } + + /** + * A callback that's called when the start of a pinch zoom is detected. + * @param {!CustomEvent<!PinchEventDetail>} e the pinch event. + * @private + */ + onPinchStart_(e) { + // We also use rAF for pinch start, so that if there is a pinch end event + // scheduled by rAF, this pinch start will be sent after. + this.window_.requestAnimationFrame(() => { + this.pinchPhase_ = Viewport.PinchPhase.PINCH_START; + this.prevScale_ = 1; + this.oldCenterInContent_ = + this.frameToContent_(this.frameToPluginCoordinate_(e.detail.center)); + + const needsScrollbars = this.documentNeedsScrollbars(this.getZoom()); + this.keepContentCentered_ = !needsScrollbars.horizontal; + // We keep track of beginning of the pinch. + // By doing so we will be able to compute the pan distance. + this.firstPinchCenterInFrame_ = e.detail.center; + }); + } } /** @@ -1274,11 +1496,15 @@ Viewport.PinchPhase = { * keys are pressed. Usually we just let the browser handle scrolling on the * window when these keys are pressed but in certain cases we need to simulate * these events. + * @type {number} */ -Viewport.SCROLL_INCREMENT = 40; +const SCROLL_INCREMENT = 40; -/** The width of the page shadow around pages in pixels. */ -Viewport.PAGE_SHADOW = { +/** + * The width of the page shadow around pages in pixels. + * @type {!{top: number, bottom: number, left: number, right: number}} + */ +export const PAGE_SHADOW = { top: 3, bottom: 7, left: 5, diff --git a/chromium/chrome/browser/resources/pdf/viewport_scroller.js b/chromium/chrome/browser/resources/pdf/viewport_scroller.js index c0d8fe4f45f..8d0186ce3d9 100644 --- a/chromium/chrome/browser/resources/pdf/viewport_scroller.js +++ b/chromium/chrome/browser/resources/pdf/viewport_scroller.js @@ -2,12 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * Creates a new ViewportScroller. - * A ViewportScroller scrolls the page in response to drag selection with the - * mouse. - * - */ +// Scrolls the page in response to drag selection with the mouse. export class ViewportScroller { /** * @param {Object} viewport The viewport info of the page. @@ -27,7 +22,6 @@ export class ViewportScroller { /** * Start scrolling the page by |scrollVelocity_| every * |DRAG_TIMER_INTERVAL_MS_|. - * * @private */ startDragScrollTimer_() { @@ -41,7 +35,6 @@ export class ViewportScroller { /** * Stops the drag scroll timer if it is active. - * * @private */ stopDragScrollTimer_() { @@ -54,7 +47,6 @@ export class ViewportScroller { /** * Scrolls the viewport by the current scroll velocity. - * * @private */ dragScrollPage_() { @@ -71,7 +63,6 @@ export class ViewportScroller { /** * Calculate the velocity to scroll while dragging using the distance of the * cursor outside the viewport. - * * @param {Object} event The mousemove event. * @return {Object} Object with x and y direction scroll velocity. * @private @@ -95,7 +86,6 @@ export class ViewportScroller { /** * Handles mousemove events. It updates the scroll velocity and starts and * stops timer based on scroll velocity. - * * @param {Object} event The mousemove event. * @private */ @@ -111,7 +101,6 @@ export class ViewportScroller { /** * Sets whether to scroll the viewport when the mouse is outside the * viewport. - * * @param {boolean} isSelecting Represents selection status. */ setEnableScrolling(isSelecting) { @@ -134,14 +123,12 @@ export class ViewportScroller { /** * The period of time in milliseconds to wait between updating the viewport * position by the scroll velocity. - * * @private */ ViewportScroller.DRAG_TIMER_INTERVAL_MS_ = 100; /** * The maximum drag scroll distance per DRAG_TIMER_INTERVAL in pixels. - * * @private */ ViewportScroller.MAX_DRAG_SCROLL_DISTANCE_ = 100; diff --git a/chromium/chrome/browser/resources/pdf/zoom_manager.js b/chromium/chrome/browser/resources/pdf/zoom_manager.js index bb4e687e02c..bab9f2ec738 100644 --- a/chromium/chrome/browser/resources/pdf/zoom_manager.js +++ b/chromium/chrome/browser/resources/pdf/zoom_manager.js @@ -6,11 +6,8 @@ import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_t import {BrowserApi} from './browser_api.js'; -/** - * Abstract parent of classes that manage updating the browser - * with zoom changes and/or updating the viewer's zoom when - * the browser zoom changes. - */ +// Abstract parent of classes that manage updating the browser with zoom changes +// and/or updating the viewer's zoom when the browser zoom changes. export class ZoomManager { /** * @param {function():number} getViewportZoom Callback to get the viewport's @@ -39,7 +36,6 @@ export class ZoomManager { /** * Creates the appropriate kind of zoom manager given the zoom behavior. - * * @param {BrowserApi.ZoomBehavior} zoomBehavior How to manage zoom. * @param {function():number} getViewportZoom A function that gets the current * viewport zoom. @@ -62,20 +58,16 @@ export class ZoomManager { /** * Invoked when a browser-initiated zoom-level change occurs. - * * @param {number} newZoom the zoom level to zoom to. */ onBrowserZoomChange(newZoom) {} - /** - * Invoked when an extension-initiated zoom-level change occurs. - */ + /** Invoked when an extension-initiated zoom-level change occurs. */ onPdfZoomChange() {} /** * Combines the internal pdf zoom and the browser zoom to * produce the total zoom level for the viewer. - * * @param {number} internalZoom the zoom level internal to the viewer. * @return {number} the total zoom level. */ @@ -86,7 +78,6 @@ export class ZoomManager { /** * Given a zoom level, return the internal zoom level needed to * produce that zoom level. - * * @param {number} totalZoom the total zoom level. * @return {number} the zoom level internal to the viewer. */ @@ -96,7 +87,6 @@ export class ZoomManager { /** * Returns whether two numbers are approximately equal. - * * @param {number} a The first number. * @param {number} b The second number. */ @@ -109,15 +99,11 @@ export class ZoomManager { } } -/** - * InactiveZoomManager has no control over the browser's zoom - * and does not respond to browser zoom changes. - */ +// Has no control over the browser's zoom and does not respond to browser zoom +// changes. export class InactiveZoomManager extends ZoomManager {} -/** - * ActiveZoomManager controls the browser's zoom. - */ +// ActiveZoomManager controls the browser's zoom. class ActiveZoomManager extends ZoomManager { /** * Constructs a ActiveZoomManager. @@ -139,7 +125,6 @@ class ActiveZoomManager extends ZoomManager { /** * Invoked when a browser-initiated zoom-level change occurs. - * * @param {number} newZoom the zoom level to zoom to. */ onBrowserZoomChange(newZoom) { @@ -193,7 +178,6 @@ class ActiveZoomManager extends ZoomManager { /** * Combines the internal pdf zoom and the browser zoom to * produce the total zoom level for the viewer. - * * @param {number} internalZoom the zoom level internal to the viewer. * @return {number} the total zoom level. */ @@ -206,7 +190,6 @@ class ActiveZoomManager extends ZoomManager { /** * Given a zoom level, return the internal zoom level needed to * produce that zoom level. - * * @param {number} totalZoom the total zoom level. * @return {number} the zoom level internal to the viewer. */ @@ -217,14 +200,11 @@ class ActiveZoomManager extends ZoomManager { } } -/** - * This EmbeddedZoomManager responds to changes in the browser zoom, - * but does not control the browser zoom. - */ +// Responds to changes in the browser zoom, but does not control the browser +// zoom. class EmbeddedZoomManager extends ZoomManager { /** * Invoked when a browser-initiated zoom-level change occurs. - * * @param {number} newZoom the new browser zoom level. */ onBrowserZoomChange(newZoom) { diff --git a/chromium/chrome/browser/resources/print_preview/BUILD.gn b/chromium/chrome/browser/resources/print_preview/BUILD.gn index 63df1dd2a18..abe2ff3da74 100644 --- a/chromium/chrome/browser/resources/print_preview/BUILD.gn +++ b/chromium/chrome/browser/resources/print_preview/BUILD.gn @@ -44,7 +44,7 @@ if (optimize_webui) { ] deps = [ - "../pdf/elements:web_components", + "../pdf:web_components", "ui:web_components", ] defines = chrome_grit_defines @@ -74,10 +74,23 @@ js_type_check("print_preview_module_resources") { ":dark_mode_behavior", ":metrics", ":native_layer", + ":print_preview", ":print_preview_utils", ] } +js_library("print_preview") { + deps = [ + ":cloud_print_interface", + ":native_layer", + "data:destination", + "data:destination_store", + "data:measurement_system", + "ui:app", + "ui:settings_select", + ] +} + js_library("print_preview_utils") { deps = [ ":dark_mode_behavior", @@ -118,6 +131,7 @@ js_library("native_layer") { "data:destination_match", "data:destination_policies", "data:measurement_system", + "data:printer_status_cros", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", ] diff --git a/chromium/chrome/browser/resources/print_preview/data/BUILD.gn b/chromium/chrome/browser/resources/print_preview/data/BUILD.gn index 030f5a2088f..61a94abfa0a 100644 --- a/chromium/chrome/browser/resources/print_preview/data/BUILD.gn +++ b/chromium/chrome/browser/resources/print_preview/data/BUILD.gn @@ -22,6 +22,7 @@ js_type_check("closure_compile_module") { ":measurement_system", ":model", ":printable_area", + ":printer_status_cros", ":scaling", ":size", ":state", @@ -165,3 +166,6 @@ js_library("user_manager") { "//ui/webui/resources/js:web_ui_listener_behavior.m", ] } + +js_library("printer_status_cros") { +} diff --git a/chromium/chrome/browser/resources/print_preview/data/destination.js b/chromium/chrome/browser/resources/print_preview/data/destination.js index 3c6155bd266..a6938175df1 100644 --- a/chromium/chrome/browser/resources/print_preview/data/destination.js +++ b/chromium/chrome/browser/resources/print_preview/data/destination.js @@ -10,6 +10,7 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; // <if expr="chromeos"> import {ColorModeRestriction, DestinationPolicies, DuplexModeRestriction, PinModeRestriction} from './destination_policies.js'; +import {PrinterStatusReason} from '../data/printer_status_cros.js'; // </if> /** @@ -139,7 +140,7 @@ export let VendorCapability; * only on Chrome OS. * * @typedef {{ - * vendor_capability: !Array<!VendorCapability>, + * vendor_capability: (Array<!VendorCapability>|undefined), * collate: ({default: (boolean|undefined)}|undefined), * color: ({ * option: !Array<{ @@ -162,7 +163,8 @@ export let VendorCapability; * type: (string|undefined), * vendor_id: (string|undefined), * custom_display_name: (string|undefined), - * is_default: (boolean|undefined) + * is_default: (boolean|undefined), + * name: (string|undefined), * }> * }|undefined), * dpi: ({ @@ -412,6 +414,12 @@ export class Destination { * @private {string} */ this.eulaUrl_ = ''; + + /** + * Stores the printer status reason for a local Chrome OS printer. + * @private {!PrinterStatusReason} + */ + this.printerStatusReason_ = PrinterStatusReason.UNKNOWN_REASON; // </if> assert( @@ -597,6 +605,22 @@ export class Destination { set eulaUrl(eulaUrl) { this.eulaUrl_ = eulaUrl; } + + /** + * @return {!PrinterStatusReason} The printer status reason for a local + * Chrome OS printer. + */ + get printerStatusReason() { + return this.printerStatusReason_; + } + + /** + * @param {!PrinterStatusReason} printerStatusReason The printer status reason + * to be set. + */ + set printerStatusReason(printerStatusReason) { + this.printerStatusReason_ = printerStatusReason; + } // </if> /** 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 f8b40cdd974..2844928fe10 100644 --- a/chromium/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chromium/chrome/browser/resources/print_preview/data/destination_store.js @@ -10,7 +10,7 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {CloudPrintInterface, CloudPrintInterfaceEventType, CloudPrintInterfacePrinterFailedDetail, CloudPrintInterfaceProcessInviteDetail, CloudPrintInterfaceSearchDoneDetail} from '../cloud_print_interface.js'; import {Metrics, MetricsContext} from '../metrics.js'; -import {CapabilitiesResponse, LocalDestinationInfo, NativeLayer, PrinterSetupResponse, PrivetPrinterDescription, ProvisionalDestinationInfo} from '../native_layer.js'; +import {CapabilitiesResponse, LocalDestinationInfo, NativeLayer, NativeLayerImpl, PrinterSetupResponse, PrivetPrinterDescription, ProvisionalDestinationInfo} from '../native_layer.js'; import {Cdd, CloudOrigins, createDestinationKey, createRecentDestinationKey, Destination, DestinationConnectionStatus, DestinationOrigin, DestinationProvisionalType, DestinationType, RecentDestination} from './destination.js'; import {DestinationMatch, originToType, PrinterType} from './destination_match.js'; @@ -229,7 +229,7 @@ export class DestinationStore extends EventTarget { * Used to fetch local print destinations. * @private {!NativeLayer} */ - this.nativeLayer_ = NativeLayer.getInstance(); + this.nativeLayer_ = NativeLayerImpl.getInstance(); /** * Whether PDF printer is enabled. It's disabled, for example, in App diff --git a/chromium/chrome/browser/resources/print_preview/data/model.js b/chromium/chrome/browser/resources/print_preview/data/model.js index 8eea52a6e5f..b0a3948e24e 100644 --- a/chromium/chrome/browser/resources/print_preview/data/model.js +++ b/chromium/chrome/browser/resources/print_preview/data/model.js @@ -10,7 +10,7 @@ import {Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.m import {BackgroundGraphicsModeRestriction, Policies} from '../native_layer.js'; -import {Cdd, CddCapabilities, Destination, DestinationOrigin, DestinationType, RecentDestination} from './destination.js'; +import {Cdd, CddCapabilities, Destination, DestinationOrigin, DestinationType, RecentDestination, VendorCapability} from './destination.js'; import {getPrinterTypeForDestination} from './destination_match.js'; // <if expr="chromeos"> import {ColorModeRestriction, DuplexModeRestriction, PinModeRestriction} from './destination_policies.js'; @@ -44,6 +44,7 @@ export let Setting; * collate: !Setting, * layout: !Setting, * color: !Setting, + * customMargins: !Setting, * mediaSize: !Setting, * margins: !Setting, * dpi: !Setting, @@ -950,7 +951,8 @@ Polymer({ if (this.settings.vendorItems.available) { const vendorSettings = {}; - for (const item of caps.vendor_capability) { + for (const item of /** @type {!Array<!VendorCapability>} */ ( + caps.vendor_capability)) { let defaultValue = null; if (item.type === 'SELECT' && item.select_cap && item.select_cap.option) { diff --git a/chromium/chrome/browser/resources/print_preview/data/printer_status_cros.js b/chromium/chrome/browser/resources/print_preview/data/printer_status_cros.js new file mode 100644 index 00000000000..0cc0c513121 --- /dev/null +++ b/chromium/chrome/browser/resources/print_preview/data/printer_status_cros.js @@ -0,0 +1,56 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * These values must be kept in sync with the Reason enum in + * /chromeos/printing/cups_printer_status.h + * @enum {number} + */ +export const PrinterStatusReason = { + CONNECTING_TO_DEVICE: 0, + DEVICE_ERROR: 1, + DOOR_OPEN: 2, + LOW_ON_INK: 3, + LOW_ON_PAPER: 4, + NO_ERROR: 5, + OUT_OF_INK: 6, + OUT_OF_PAPER: 7, + OUTPUT_ALMOST_FULL: 8, + OUTPUT_FULL: 9, + PAPER_JAM: 10, + PAUSED: 11, + PRINTER_QUEUE_FULL: 12, + PRINTER_UNREACHABLE: 13, + STOPPED: 14, + TRAY_MISSING: 15, + UNKNOWN_REASON: 16, +}; + +/** + * These values must be kept in sync with the Severity enum in + * /chromeos/printing/cups_printer_status.h + * @enum {number} + */ +export const PrinterStatusSeverity = { + UNKOWN_SEVERITY: 0, + REPORT: 1, + WARNING: 2, + ERROR: 3, +}; + +/** + * A container for the results of a printer status query. A printer status query + * can return multiple error reasons. |timestamp| is set at the time of status + * creation. + * + * @typedef {{ + * printerId: string, + * statusReasons: !Array<{ + * reason: PrinterStatusReason, + * severity: PrinterStatusSeverity, + * }>, + * timestamp: number, + * }} + */ +export let PrinterStatus; diff --git a/chromium/chrome/browser/resources/print_preview/metrics.js b/chromium/chrome/browser/resources/print_preview/metrics.js index 34325bc2883..dc889e6ad99 100644 --- a/chromium/chrome/browser/resources/print_preview/metrics.js +++ b/chromium/chrome/browser/resources/print_preview/metrics.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {NativeLayer} from './native_layer.js'; +import {NativeLayer, NativeLayerImpl} from './native_layer.js'; /** * Object used to measure usage statistics. @@ -89,7 +89,7 @@ export class MetricsContext { this.maxBucket_ = maxBucket; /** @private {!NativeLayer} */ - this.nativeLayer_ = NativeLayer.getInstance(); + this.nativeLayer_ = NativeLayerImpl.getInstance(); } /** diff --git a/chromium/chrome/browser/resources/print_preview/native_layer.js b/chromium/chrome/browser/resources/print_preview/native_layer.js index ff0c3d18686..a7f13fc56bb 100644 --- a/chromium/chrome/browser/resources/print_preview/native_layer.js +++ b/chromium/chrome/browser/resources/print_preview/native_layer.js @@ -3,12 +3,13 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.m.js'; -import {sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js'; import {Cdd, Destination} from './data/destination.js'; import {PrinterType} from './data/destination_match.js'; // <if expr="chromeos"> import {DestinationPolicies} from './data/destination_policies.js'; +import {PrinterStatus} from './data/printer_status_cros.js'; // </if> import {MeasurementSystemUnitType} from './data/measurement_system.js'; @@ -118,7 +119,7 @@ export let PrivetPrinterDescription; * printer:(PrivetPrinterDescription | * LocalDestinationInfo | * undefined), - * capabilities: !Cdd, + * capabilities: ?Cdd, * }} */ export let CapabilitiesResponse; @@ -146,44 +147,22 @@ export let ProvisionalDestinationInfo; /** * An interface to the native Chromium printing system layer. + * @interface */ export class NativeLayer { - /** - * Creates a new NativeLayer if the current instance is not set. - * @return {!NativeLayer} The singleton instance. - */ - static getInstance() { - if (currentInstance === null) { - currentInstance = new NativeLayer(); - } - return assert(currentInstance); - } - - /** - * @param {!NativeLayer} instance The NativeLayer instance - * to set for print preview construction. - */ - static setInstance(instance) { - currentInstance = instance; - } - // <if expr="chromeos"> /** * Requests access token for cloud print requests for DEVICE origin. * @return {!Promise<string>} */ - getAccessToken() { - return sendWithPromise('getAccessToken'); - } + getAccessToken() {} // </if> /** * Gets the initial settings to initialize the print preview with. * @return {!Promise<!NativeInitialSettings>} */ - getInitialSettings() { - return sendWithPromise('getInitialSettings'); - } + getInitialSettings() {} /** * Requests the system's print destinations. The promise will be resolved @@ -193,9 +172,7 @@ export class NativeLayer { * request. * @return {!Promise} */ - getPrinters(type) { - return sendWithPromise('getPrinters', type); - } + getPrinters(type) {} /** * Requests the destination's printing capabilities. Returns a promise that @@ -204,13 +181,7 @@ export class NativeLayer { * @param {!PrinterType} type The destination's printer type. * @return {!Promise<!CapabilitiesResponse>} */ - getPrinterCapabilities(destinationId, type) { - return sendWithPromise( - 'getPrinterCapabilities', destinationId, - destinationId === Destination.GooglePromotedId.SAVE_AS_PDF ? - PrinterType.PDF_PRINTER : - type); - } + getPrinterCapabilities(destinationId, type) {} // <if expr="chromeos"> /** @@ -220,9 +191,7 @@ export class NativeLayer { * @param {!string} destinationId ID of the destination. * @return {!Promise<string>} */ - getEulaUrl(destinationId) { - return sendWithPromise('getEulaUrl', destinationId); - } + getEulaUrl(destinationId) {} /** * Requests Chrome to resolve provisional extension destination by granting @@ -230,19 +199,14 @@ export class NativeLayer { * @param {string} provisionalDestinationId * @return {!Promise<!ProvisionalDestinationInfo>} */ - grantExtensionPrinterAccess(provisionalDestinationId) { - return sendWithPromise( - 'grantExtensionPrinterAccess', provisionalDestinationId); - } + grantExtensionPrinterAccess(provisionalDestinationId) {} /** * Requests that Chrome perform printer setup for the given printer. * @param {string} printerId * @return {!Promise<!PrinterSetupResponse>} */ - setupPrinter(printerId) { - return sendWithPromise('setupPrinter', printerId); - } + setupPrinter(printerId) {} // </if> /** @@ -256,17 +220,13 @@ export class NativeLayer { * @return {!Promise<number>} Promise that resolves with the unique ID of * the preview UI when the preview has been generated. */ - getPreview(printTicket) { - return sendWithPromise('getPreview', printTicket); - } + getPreview(printTicket) {} /** * Opens the chrome://settings printing page. For Chrome OS, open the - * printing settings in the Settings App. + * printing settings in the Settings App. */ - openSettingsPrintPage() { - chrome.send('openPrinterSettings'); - } + openSettingsPrintPage() {} /** * Requests that the document be printed. @@ -275,28 +235,20 @@ export class NativeLayer { * @return {!Promise} Promise that will resolve when the print request is * finished or rejected. */ - print(printTicket) { - return sendWithPromise('print', printTicket); - } + print(printTicket) {} /** Requests that the current pending print request be cancelled. */ - cancelPendingPrintRequest() { - chrome.send('cancelPendingPrintRequest'); - } + cancelPendingPrintRequest() {} /** * Sends the app state to be saved in the sticky settings. * @param {string} appStateStr JSON string of the app state to persist. */ - saveAppState(appStateStr) { - chrome.send('saveAppState', [appStateStr]); - } + saveAppState(appStateStr) {} // <if expr="not chromeos and not is_win"> /** Shows the system's native printing dialog. */ - showSystemDialog() { - chrome.send('showSystemDialog'); - } + showSystemDialog() {} // </if> /** @@ -306,17 +258,10 @@ export class NativeLayer { * @param {boolean} isCancel whether this was called due to the user * closing the dialog without printing. */ - dialogClose(isCancel) { - if (isCancel) { - chrome.send('closePrintPreviewDialog'); - } - chrome.send('dialogClose'); - } + dialogClose(isCancel) {} /** Hide the print preview dialog and allow the native layer to close it. */ - hidePreview() { - chrome.send('hidePreview'); - } + hidePreview() {} /** * Opens the Google Cloud Print sign-in tab. If the user signs in @@ -324,26 +269,16 @@ export class NativeLayer { * @param {boolean} addAccount Whether to open an 'add a new account' or * default sign in page. */ - signIn(addAccount) { - chrome.send('signIn', [addAccount]); - } - - /** - * Sends a message to the test, letting it know that an - * option has been set to a particular value and that the change has - * finished modifying the preview area. - */ - uiLoadedForTest() { - chrome.send('UILoadedForTest'); - } + signIn(addAccount) {} + // <if expr="chromeos"> /** - * Notifies the test that the option it tried to change - * had not been changed successfully. + * Sends a request to the printer with id |printerId| for its current status. + * @param {string} printerId + * @return {!Promise<!PrinterStatus>} */ - uiFailedLoadingForTest() { - chrome.send('UIFailedLoadingForTest'); - } + requestPrinterStatusUpdate(printerId) {} + // </if> /** * Notifies the metrics handler to record a histogram value. @@ -351,11 +286,117 @@ export class NativeLayer { * @param {number} bucket The bucket to record * @param {number} maxBucket The maximum bucket value in the histogram. */ + recordInHistogram(histogram, bucket, maxBucket) {} +} + +/** @implements {NativeLayer} */ +export class NativeLayerImpl { + // <if expr="chromeos"> + /** @override */ + getAccessToken() { + return sendWithPromise('getAccessToken'); + } + // </if> + + /** @override */ + getInitialSettings() { + return sendWithPromise('getInitialSettings'); + } + + /** @override */ + getPrinters(type) { + return sendWithPromise('getPrinters', type); + } + + /** @override */ + getPrinterCapabilities(destinationId, type) { + return sendWithPromise( + 'getPrinterCapabilities', destinationId, + destinationId === Destination.GooglePromotedId.SAVE_AS_PDF ? + PrinterType.PDF_PRINTER : + type); + } + + // <if expr="chromeos"> + /** @override */ + getEulaUrl(destinationId) { + return sendWithPromise('getEulaUrl', destinationId); + } + + /** @override */ + grantExtensionPrinterAccess(provisionalDestinationId) { + return sendWithPromise( + 'grantExtensionPrinterAccess', provisionalDestinationId); + } + + /** @override */ + setupPrinter(printerId) { + return sendWithPromise('setupPrinter', printerId); + } + // </if> + + /** @override */ + getPreview(printTicket) { + return sendWithPromise('getPreview', printTicket); + } + + /** @override */ + openSettingsPrintPage() { + chrome.send('openPrinterSettings'); + } + + /** @override */ + print(printTicket) { + return sendWithPromise('print', printTicket); + } + + /** @override */ + cancelPendingPrintRequest() { + chrome.send('cancelPendingPrintRequest'); + } + + /** @override */ + saveAppState(appStateStr) { + chrome.send('saveAppState', [appStateStr]); + } + + // <if expr="not chromeos and not is_win"> + /** @override */ + showSystemDialog() { + chrome.send('showSystemDialog'); + } + // </if> + + /** @override */ + dialogClose(isCancel) { + if (isCancel) { + chrome.send('closePrintPreviewDialog'); + } + chrome.send('dialogClose'); + } + + /** @override */ + hidePreview() { + chrome.send('hidePreview'); + } + + /** @override */ + signIn(addAccount) { + chrome.send('signIn', [addAccount]); + } + + // <if expr="chromeos"> + /** @override */ + requestPrinterStatusUpdate(printerId) { + return sendWithPromise('requestPrinterStatus', printerId); + } + // </if> + + /** @override */ recordInHistogram(histogram, bucket, maxBucket) { chrome.send( 'metricsHandler:recordInHistogram', [histogram, bucket, maxBucket]); } } -/** @private {?NativeLayer} */ -let currentInstance = null; +addSingletonGetter(NativeLayerImpl); diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.html b/chromium/chrome/browser/resources/print_preview/print_preview.html index 4aa26d79dbd..6a792ccc483 100644 --- a/chromium/chrome/browser/resources/print_preview/print_preview.html +++ b/chromium/chrome/browser/resources/print_preview/print_preview.html @@ -1,6 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{a11yenhanced} - class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> <head> <title>$i18n{title}</title> <meta charset="utf-8"> diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.js b/chromium/chrome/browser/resources/print_preview/print_preview.js index 21658c88e7f..10d3ac4aae4 100644 --- a/chromium/chrome/browser/resources/print_preview/print_preview.js +++ b/chromium/chrome/browser/resources/print_preview/print_preview.js @@ -4,25 +4,30 @@ import './ui/app.js'; +export {PluralStringProxyImpl as PrintPreviewPluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; export {CloudPrintInterface, CloudPrintInterfaceEventType} from './cloud_print_interface.js'; export {CloudPrintInterfaceImpl} from './cloud_print_interface_impl.js'; -export {ColorMode, createDestinationKey, Destination, DestinationCertificateStatus, DestinationConnectionStatus, DestinationOrigin, DestinationType, makeRecentDestination} from './data/destination.js'; +export {ColorMode, createDestinationKey, Destination, DestinationCertificateStatus, DestinationConnectionStatus, DestinationOrigin, DestinationType, makeRecentDestination, RecentDestination} from './data/destination.js'; export {PrinterType} from './data/destination_match.js'; // <if expr="chromeos"> export {ColorModeRestriction, DuplexModeRestriction, PinModeRestriction} from './data/destination_policies.js'; +export {PrinterStatus, PrinterStatusReason, PrinterStatusSeverity} from './data/printer_status_cros.js'; +export {PrinterState} from './ui/printer_status_icon_cros.js'; // </if> export {DestinationErrorType, DestinationStore} from './data/destination_store.js'; +export {PageLayoutInfo} from './data/document_info.js'; export {InvitationStore} from './data/invitation_store.js'; -export {CustomMarginsOrientation, Margins, MarginsType} from './data/margins.js'; +export {CustomMarginsOrientation, Margins, MarginsSetting, MarginsType} from './data/margins.js'; export {MeasurementSystem, MeasurementSystemUnitType} from './data/measurement_system.js'; export {DuplexMode, DuplexType, getInstance, whenReady} from './data/model.js'; export {ScalingType} from './data/scaling.js'; export {Size} from './data/size.js'; export {Error, State} from './data/state.js'; -export {BackgroundGraphicsModeRestriction, NativeLayer} from './native_layer.js'; +export {BackgroundGraphicsModeRestriction, CapabilitiesResponse, LocalDestinationInfo, NativeInitialSettings, NativeLayer, NativeLayerImpl, PrinterSetupResponse, ProvisionalDestinationInfo} from './native_layer.js'; export {getSelectDropdownBackground} from './print_preview_utils.js'; export {DEFAULT_MAX_COPIES} from './ui/copies_settings.js'; export {DestinationState} from './ui/destination_settings.js'; export {PluginProxy} from './ui/plugin_proxy.js'; export {PreviewAreaState} from './ui/preview_area.js'; export {SelectBehavior} from './ui/select_behavior.js'; +export {SelectOption} from './ui/settings_select.js'; diff --git a/chromium/chrome/browser/resources/print_preview/print_preview_pdf_resources.grd b/chromium/chrome/browser/resources/print_preview/print_preview_pdf_resources.grd new file mode 100644 index 00000000000..d8483272925 --- /dev/null +++ b/chromium/chrome/browser/resources/print_preview/print_preview_pdf_resources.grd @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/print_preview_pdf_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/print_preview_pdf_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/print_preview_pdf_resources_map.h" + type="resource_map_header" /> + <output filename="print_preview_pdf_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <include name="IDR_PRINT_PREVIEW_PDF_INDEX_PP_HTML" + file="../pdf/index_pp.html" + type="BINDATA" /> + <include name="IDR_PRINT_PREVIEW_PDF_PDF_VIEWER_PP_JS" + file="${root_gen_dir}/chrome/browser/resources/pdf/pdf_viewer_pp.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_PRINT_PREVIEW_PDF_VIEWER_PAGE_INDICATOR_JS" + file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-page-indicator.js" + use_base_dir="false" + type="BINDATA" /> + </includes> + </release> +</grit> diff --git a/chromium/chrome/browser/resources/print_preview/print_preview_resources.grd b/chromium/chrome/browser/resources/print_preview/print_preview_resources.grd index 8f7cd3fe0b5..9bbd50d630f 100644 --- a/chromium/chrome/browser/resources/print_preview/print_preview_resources.grd +++ b/chromium/chrome/browser/resources/print_preview/print_preview_resources.grd @@ -49,6 +49,12 @@ <include name="IDR_PRINT_PREVIEW_UI_DESTINATION_SELECT_CROS_JS" file="${root_gen_dir}/chrome/browser/resources/print_preview/ui/destination_select_cros.js" use_base_dir="false" compress="false" type="BINDATA"/> + <include name="IDR_PRINT_PREVIEW_UI_PRINT_PREVIEW_DESTINATION_DROPDOWN_CROS_JS" + file="${root_gen_dir}/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js" + use_base_dir="false" compress="false" type="BINDATA"/> + <include name="IDR_PRINT_PREVIEW_UI_PRINT_PREVIEW_PRINTER_STATUS_ICON_CROS_JS" + file="${root_gen_dir}/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.js" + use_base_dir="false" compress="false" type="BINDATA"/> </if> <include name="IDR_PRINT_PREVIEW_UI_DESTINATION_SELECT_CSS_JS" file="${root_gen_dir}/chrome/browser/resources/print_preview/ui/destination_select_css.js" @@ -141,16 +147,6 @@ <include name="IDR_PRINT_PREVIEW_UI_ICONS_JS" file="${root_gen_dir}/chrome/browser/resources/print_preview/ui/icons.js" use_base_dir="false" compress="false" type="BINDATA"/> - <include name="IDR_PRINT_PREVIEW_PDF_INDEX_PP_HTML" - file="../pdf/index_pp.html" - type="BINDATA" /> - <include name="IDR_PRINT_PREVIEW_PDF_MAIN_PP_JS" - file="../pdf/main_pp.js" - type="BINDATA" /> - <include name="IDR_PRINT_PREVIEW_PDF_VIEWER_PAGE_INDICATOR_JS" - file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-page-indicator.js" - use_base_dir="false" - type="BINDATA" /> </includes> <structures> <structure name="IDR_PRINT_PREVIEW_PRINT_PREVIEW_HTML" @@ -196,6 +192,10 @@ file="data/destination_policies.js" compress="false" type="chrome_html" /> + <structure name="IDR_PRINT_PREVIEW_DATA_PRINTER_STATUS_CROS_JS" + file="data/printer_status_cros.js" + compress="false" + type="chrome_html" /> </if> <structure name="IDR_PRINT_PREVIEW_DATA_DESTINATION_STORE_JS" file="data/destination_store.js" diff --git a/chromium/chrome/browser/resources/print_preview/print_preview_resources_vulcanized.grd b/chromium/chrome/browser/resources/print_preview/print_preview_resources_vulcanized.grd index 0eecabc3c5d..1ac21ce8b10 100644 --- a/chromium/chrome/browser/resources/print_preview/print_preview_resources_vulcanized.grd +++ b/chromium/chrome/browser/resources/print_preview/print_preview_resources_vulcanized.grd @@ -15,23 +15,11 @@ <include name="IDR_PRINT_PREVIEW_PRINT_PREVIEW_HTML" file="print_preview.html" type="chrome_html" - preprocess="true" - compress="gzip" /> + preprocess="true" /> <include name="IDR_PRINT_PREVIEW_PRINT_PREVIEW_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\print_preview\print_preview.rollup.js" use_base_dir="false" preprocess="true" - compress="gzip" - type="BINDATA" /> - <include name="IDR_PRINT_PREVIEW_PDF_INDEX_PP_HTML" - file="../pdf/index_pp.html" - type="BINDATA" /> - <include name="IDR_PRINT_PREVIEW_PDF_MAIN_PP_JS" - file="../pdf/main_pp.js" - type="BINDATA" /> - <include name="IDR_PRINT_PREVIEW_PDF_VIEWER_PAGE_INDICATOR_JS" - file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-page-indicator.js" - use_base_dir="false" type="BINDATA" /> </includes> </release> diff --git a/chromium/chrome/browser/resources/print_preview/ui/BUILD.gn b/chromium/chrome/browser/resources/print_preview/ui/BUILD.gn index 860caec75e9..d95c0bb6565 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/BUILD.gn +++ b/chromium/chrome/browser/resources/print_preview/ui/BUILD.gn @@ -53,8 +53,10 @@ js_type_check("closure_compile_module") { if (is_chromeos) { deps += [ + ":destination_dropdown_cros", ":destination_select_cros", ":pin_settings", + ":printer_status_icon_cros", ] } else { deps += [ ":destination_select" ] @@ -117,6 +119,7 @@ js_library("button_strip") { "../data:destination", "../data:state", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:plural_string_proxy", ] if (is_chromeos) { @@ -131,6 +134,7 @@ js_library("header") { "../data:state", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:load_time_data.m", + "//ui/webui/resources/js:plural_string_proxy", ] } @@ -160,9 +164,11 @@ js_library("destination_settings") { if (is_chromeos) { js_library("destination_select_cros") { deps = [ + ":destination_dropdown_cros", ":select_behavior", "..:print_preview_utils", "../data:destination", + "../data:printer_status_cros", "//third_party/polymer/v3_0/components-chromium/iron-iconset-svg:iron-iconset-svg", "//third_party/polymer/v3_0/components-chromium/iron-meta:iron-meta", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", @@ -178,6 +184,22 @@ if (is_chromeos) { "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] } + + js_library("destination_dropdown_cros") { + deps = [ + ":printer_status_icon_cros", + "..:print_preview_utils", + "//third_party/polymer/v3_0/components-chromium/iron-dropdown:iron-dropdown", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_input:cr_input.m", + ] + } + + js_library("printer_status_icon_cros") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] + } } else { js_library("destination_select") { deps = [ @@ -544,8 +566,10 @@ html_to_js("web_components") { ] if (is_chromeos) { js_files += [ + "destination_dropdown_cros.js", "destination_select_cros.js", "pin_settings.js", + "printer_status_icon_cros.js", ] } else { js_files += [ "destination_select.js" ] diff --git a/chromium/chrome/browser/resources/print_preview/ui/app.js b/chromium/chrome/browser/resources/print_preview/ui/app.js index 575afacd7aa..5c7b6601686 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/app.js +++ b/chromium/chrome/browser/resources/print_preview/ui/app.js @@ -26,7 +26,7 @@ import {DuplexMode, whenReady} from '../data/model.js'; import {PrintableArea} from '../data/printable_area.js'; import {Size} from '../data/size.js'; import {Error, State} from '../data/state.js'; -import {NativeInitialSettings, NativeLayer} from '../native_layer.js'; +import {NativeInitialSettings, NativeLayer, NativeLayerImpl} from '../native_layer.js'; import {DestinationState} from './destination_settings.js'; import {PreviewAreaState} from './preview_area.js'; @@ -168,7 +168,7 @@ Polymer({ /** @override */ attached() { document.documentElement.classList.remove('loading'); - this.nativeLayer_ = NativeLayer.getInstance(); + this.nativeLayer_ = NativeLayerImpl.getInstance(); this.addWebUIListener('print-failed', this.onPrintFailed_.bind(this)); this.addWebUIListener( 'print-preset-options', this.onPrintPresetOptions_.bind(this)); diff --git a/chromium/chrome/browser/resources/print_preview/ui/button_strip.js b/chromium/chrome/browser/resources/print_preview/ui/button_strip.js index 28ea8d6232d..4624470278a 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/button_strip.js +++ b/chromium/chrome/browser/resources/print_preview/ui/button_strip.js @@ -8,6 +8,7 @@ import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import '../strings.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -50,7 +51,6 @@ Polymer({ /** @private */ errorMessage_: { type: String, - computed: 'computeErrorMessage_(destination.id, maxSheets, sheetCount)', observer: 'errorMessageChanged_', }, // </if> @@ -59,6 +59,9 @@ Polymer({ observers: [ 'updatePrintButtonLabel_(destination.id)', 'updatePrintButtonEnabled_(state, destination.id, maxSheets, sheetCount)', + // <if expr="chromeos"> + 'updateErrorMessage_(state, destination.id, maxSheets, sheetCount)', + // </if> ], /** @private {!State} */ @@ -140,19 +143,17 @@ Polymer({ return this.sheetCount > 0 && this.printButtonDisabled_(); }, - /** - * @return {string} Localized message to show as an error. - * @private - */ - computeErrorMessage_() { + /** @private */ + updateErrorMessage_() { if (!this.showSheetsError_()) { - return ''; + this.errorMessage_ = ''; + return; } - - const singularOrPlural = this.maxSheets > 1 ? 'Plural' : 'Singular'; - const label = loadTimeData.getString(`sheetsLimitLabel${singularOrPlural}`); - return loadTimeData.getStringF( - 'sheetsLimitErrorMessage', this.maxSheets.toLocaleString(), label); + PluralStringProxyImpl.getInstance() + .getPluralString('sheetsLimitErrorMessage', this.maxSheets) + .then(label => { + this.errorMessage_ = label; + }); }, /** diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.js b/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.js index e0532e60acf..c3b9f5bbd2c 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.js +++ b/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.js @@ -33,7 +33,7 @@ import {DestinationStore} from '../data/destination_store.js'; import {Invitation} from '../data/invitation.js'; import {InvitationStore} from '../data/invitation_store.js'; import {Metrics, MetricsContext} from '../metrics.js'; -import {NativeLayer} from '../native_layer.js'; +import {NativeLayerImpl} from '../native_layer.js'; Polymer({ is: 'print-preview-destination-dialog', @@ -129,12 +129,7 @@ Polymer({ this.$$('.promo-text').innerHTML = this.i18nAdvanced('cloudPrintPromotion', { substitutions: ['<a is="action-link" class="sign-in">', '</a>'], - attrs: { - 'is': (node, v) => v === 'action-link', - 'class': (node, v) => v === 'sign-in', - 'tabindex': (node, v) => v === '0', - 'role': (node, v) => v === 'link', - }, + attrs: ['is', 'class', 'tabindex', 'role'], }); }, @@ -340,7 +335,7 @@ Polymer({ /** @private */ onSignInClick_() { this.metrics_.record(Metrics.DestinationSearchBucket.SIGNIN_TRIGGERED); - NativeLayer.getInstance().signIn(false); + NativeLayerImpl.getInstance().signIn(false); }, /** @private */ @@ -426,7 +421,7 @@ Polymer({ this.metrics_.record(Metrics.DestinationSearchBucket.ACCOUNT_CHANGED); } else { select.value = this.activeUser; - NativeLayer.getInstance().signIn(true); + NativeLayerImpl.getInstance().signIn(true); this.metrics_.record( Metrics.DestinationSearchBucket.ADD_ACCOUNT_SELECTED); } @@ -463,6 +458,6 @@ Polymer({ /** @private */ onOpenSettingsPrintPage_() { this.metrics_.record(Metrics.DestinationSearchBucket.MANAGE_BUTTON_CLICKED); - NativeLayer.getInstance().openSettingsPrintPage(); + NativeLayerImpl.getInstance().openSettingsPrintPage(); }, }); diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html b/chromium/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html new file mode 100644 index 00000000000..c20bcbae4a6 --- /dev/null +++ b/chromium/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html @@ -0,0 +1,150 @@ +<style include="cr-shared-style cr-hidden-style md-select"> + :host([opened_]) cr-input { + --cr-input-border-radius: 4px 4px 0 0; + } + + iron-dropdown, + cr-input { + width: var(--md-select-width); + } + + cr-input::part(input) { + opacity: 1; + padding-inline-end: 32px; + padding-inline-start: 8px; + text-overflow: clip; + } + + iron-dropdown { + border: 0.5px solid rgba(0, 0, 0, 0.5); + max-height: 270px; + } + + iron-dropdown [slot='dropdown-content'] { + background-color: white; + box-shadow: 0 2px 6px var(--google-grey-600); + min-width: var(--md-select-width); + padding: 8px 0; + } + + #input-overlay { + border-radius: 4px; + height: 100%; + left: 0; + overflow: hidden; + pointer-events: none; + position: absolute; + top: 0; + width: 100%; + } + + #dropdown-icon { + --iron-icon-height: 20px; + --iron-icon-width: 20px; + margin-top: -10px; + padding-inline-end: 6px; + position: absolute; + right: 0; + top: 50%; + } + + :host-context([dir='rtl']) #dropdown-icon { + left: 0; + right: unset; + } + + cr-input:focus-within #dropdown-icon { + --iron-icon-fill-color: var(--google-blue-600); + } + + #input-box { + height: 100%; + left: 0; + pointer-events: none; + top: 0; + width: 100%; + } + + #dropdown-box { + pointer-events: initial; + width: 100%; + } + + .list-item { + background: none; + border: none; + box-sizing: border-box; + font: inherit; + min-height: 32px; + padding: 0 8px; + text-align: start; + width: 100%; + } + + .list-item:focus { + outline: none; + } + + .list-item[selected_] { + background-color: var(--google-blue-refresh-100); + } + + .dot { + background-color: #bbb; + border-radius: 50%; + display: inline-block; + height: 10px; + width: 10px; + } + + #pre-input-box, + .printer-display-name { + padding-inline-start: 8px; + } +</style> +<cr-input id="dropdownInput" on-keydown="onKeyDown_" + value="[[value.displayName]]" disabled="[[disabled]]" readonly> + <div id="pre-input-overlay" slot="inline-prefix"> + <div id="pre-input-box"> + <iron-icon icon="[[destinationIcon]]"></iron-icon> + </div> + </div> + <div id="input-overlay" slot="suffix"> + <div id="input-box"> + <iron-icon id="dropdown-icon" icon="cr:arrow-drop-down"></iron-icon> + </div> + <div id="dropdown-box"> + <iron-dropdown horizontal-align="left" vertical-align="top" + vertical-offset="0" no-cancel-on-outside-click + no-cancel-on-esc-key> + <div slot="dropdown-content"> + <template is="dom-repeat" items="[[itemList]]"> + <button id="[[item.key]]" class="list-item" on-click="onSelect_" + tabindex="-1" value="[[item.key]]"> + <printer-status-icon-cros background="white" + state$="[[computePrinterState_(item.printerStatusReason)]]"> + </printer-status-icon-cros> + <span class="printer-display-name">[[item.displayName]]</span> + </button> + </template> + <button class="list-item" on-click="onSelect_" tabindex="-1" + value="[[pdfDestinationKey]]" hidden$="[[pdfPrinterDisabled]]"> + $i18n{printToPDF} + </button> + <button class="list-item" on-click="onSelect_" tabindex="-1" + value="[[driveDestinationKey]]" hidden$="[[!driveDestinationKey]]"> + $i18n{printToGoogleDrive} + </button> + <button class="list-item" on-click="onSelect_" tabindex="-1" + value="noDestinations" hidden$="[[!noDestinations]]"> + $i18n{noDestinationsMessage} + </button> + <button class="list-item" on-click="onSelect_" tabindex="-1" + value="seeMore" aria-label$="[[i18n(seeMoreDestinationsLabel)]]"> + $i18n{seeMore} + </button> + </div> + </iron-dropdown> + </div> + </div> +</cr-input> diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js b/chromium/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js new file mode 100644 index 00000000000..3d95796c331 --- /dev/null +++ b/chromium/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js @@ -0,0 +1,273 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; +import 'chrome://resources/cr_elements/hidden_style_css.m.js'; +import 'chrome://resources/cr_elements/md_select_css.m.js'; +import 'chrome://resources/cr_elements/shared_vars_css.m.js'; +// TODO(gavinwill): Remove iron-dropdown dependency https://crbug.com/1082587. +import 'chrome://resources/polymer/v3_0/iron-dropdown/iron-dropdown.js'; +import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; + +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {Destination} from '../data/destination.js'; +import {PrinterStatusReason} from '../data/printer_status_cros.js'; + +import {PrinterState} from './printer_status_icon_cros.js'; + +Polymer({ + is: 'print-preview-destination-dropdown-cros', + + _template: html`{__html_template__}`, + + properties: { + /** @type {!Destination} */ + value: Object, + + /** @type {!Array<!Destination>} */ + itemList: { + type: Array, + observer: 'enqueueDropdownRefit_', + }, + + /** @type {boolean} */ + disabled: { + type: Boolean, + value: false, + }, + + driveDestinationKey: String, + + noDestinations: Boolean, + + pdfPrinterDisabled: Boolean, + + pdfDestinationKey: String, + + destinationIcon: String, + }, + + listeners: { + 'mousemove': 'onMouseMove_', + }, + + /** @override */ + attached() { + this.pointerDownListener_ = event => this.onPointerDown_(event); + document.addEventListener('pointerdown', this.pointerDownListener_); + }, + + /** @override */ + detached() { + document.removeEventListener('pointerdown', this.pointerDownListener_); + }, + + /** + * Enqueues a task to refit the iron-dropdown if it is open. + * @private + */ + enqueueDropdownRefit_() { + const dropdown = this.$$('iron-dropdown'); + if (!this.dropdownRefitPending_ && dropdown.opened) { + this.dropdownRefitPending_ = true; + setTimeout(() => { + dropdown.refit(); + this.dropdownRefitPending_ = false; + }, 0); + } + }, + + /** @private */ + openDropdown_() { + if (this.disabled) { + return; + } + + this.$$('iron-dropdown').open(); + this.opened_ = true; + }, + + /** @private */ + closeDropdown_() { + this.$$('iron-dropdown').close(); + this.opened_ = false; + + const selectedItem = this.findSelectedItem_(); + if (selectedItem) { + selectedItem.removeAttribute('selected_'); + } + }, + + /** + * @param {!Event} event + * @private + */ + onMouseMove_(event) { + const item = event.composedPath().find( + elm => elm.classList && elm.classList.contains('list-item')); + if (!item) { + return; + } + + // Select the item the mouse is hovering over. If the user uses the + // keyboard, the selection will shift. But once the user moves the mouse, + // selection should be updated based on the location of the mouse cursor. + const selectedItem = this.findSelectedItem_(); + if (item === selectedItem) { + return; + } + + if (selectedItem) { + selectedItem.removeAttribute('selected_'); + } + item.setAttribute('selected_', ''); + }, + + /** + * @param {!Event} event + * @private + */ + onPointerDown_(event) { + const paths = event.composedPath(); + const dropdown = + /** @type {!IronDropdownElement} */ (this.$$('iron-dropdown')); + const dropdownInput = + /** @type {!CrInputElement} */ (this.$$('#dropdownInput')); + + // Exit if path includes |dropdown| because event will be handled by + // onSelect_. + if (paths.includes(dropdown)) { + return; + } + + if (!paths.includes(dropdownInput) || dropdown.opened) { + this.closeDropdown_(); + return; + } + + this.openDropdown_(); + }, + + /** @private */ + onSelect_() { + const selectedItem = this.findSelectedItem_(); + this.closeDropdown_(); + this.fire('dropdown-value-selected', selectedItem); + }, + + /** + * @param {!Event} event + * @private + */ + onKeyDown_(event) { + event.stopPropagation(); + const dropdown = this.$$('iron-dropdown'); + switch (event.code) { + case 'Tab': + this.closeDropdown_(); + break; + case 'ArrowUp': + case 'ArrowDown': { + const items = dropdown.getElementsByClassName('list-item'); + if (items.length === 0) { + break; + } + this.updateSelected_(event.code === 'ArrowDown'); + break; + } + case 'Enter': { + if (dropdown.opened) { + this.onSelect_(); + break; + } + this.openDropdown_(); + break; + } + case 'Escape': { + if (dropdown.opened) { + this.closeDropdown_(); + event.preventDefault(); + } + break; + } + } + }, + + /** + * Updates the currently selected element based on keyboard up/down movement. + * @param {boolean} moveDown + * @private + */ + updateSelected_(moveDown) { + const items = this.getButtonListFromDropdown_(); + const numItems = items.length; + if (numItems === 0) { + return; + } + + let nextIndex = 0; + const currentIndex = this.findSelectedItemIndex_(); + if (currentIndex === -1) { + nextIndex = moveDown ? 0 : numItems - 1; + } else { + const delta = moveDown ? 1 : -1; + nextIndex = (numItems + currentIndex + delta) % numItems; + items[currentIndex].removeAttribute('selected_'); + } + items[nextIndex].setAttribute('selected_', ''); + // The newly selected item might not be visible because the dropdown needs + // to be scrolled. So scroll the dropdown if necessary. + items[nextIndex].scrollIntoViewIfNeeded(); + }, + + /** + * Finds the currently selected dropdown item. + * @return {Element|undefined} Currently selected dropdown item, or undefined + * if no item is selected. + * @private + */ + findSelectedItem_() { + const items = this.getButtonListFromDropdown_(); + return items.find(item => item.hasAttribute('selected_')); + }, + + /** + * Finds the index of currently selected dropdown item. + * @return {number} Index of the currently selected dropdown item, or -1 if + * no item is selected. + * @private + */ + findSelectedItemIndex_() { + const items = this.getButtonListFromDropdown_(); + return items.findIndex(item => item.hasAttribute('selected_')); + }, + + /** + * Returns list of all the visible items in the dropdown. + * @return {!Array<!Element>} + * @private + */ + getButtonListFromDropdown_() { + const dropdown = this.$$('iron-dropdown'); + return Array.from(dropdown.getElementsByClassName('list-item')) + .filter(item => !item.hidden); + }, + + /** + * @param {?PrinterStatusReason} printerStatusReason + * @return {number} + * @private + */ + computePrinterState_(printerStatusReason) { + if (!printerStatusReason || + printerStatusReason === PrinterStatusReason.UNKNOWN_REASON) { + return PrinterState.UNKNOWN; + } + if (printerStatusReason === PrinterStatusReason.NO_ERROR) { + return PrinterState.GOOD; + } + return PrinterState.ERROR; + }, +}); diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_select_cros.html b/chromium/chrome/browser/resources/print_preview/ui/destination_select_cros.html index 2d8d0b8d28f..9ef6b0878c1 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/destination_select_cros.html +++ b/chromium/chrome/browser/resources/print_preview/ui/destination_select_cros.html @@ -7,8 +7,8 @@ <div class="throbber"></div> </div> <template is="dom-if" if="[[!printerStatusFlagEnabled_]]"> - <select class="md-select" aria-label$="[[i18n(destinationLabel)]]" - hidden$="[[!loaded]]" + <select id="dropdown" class="md-select" + aria-label$="[[i18n(destinationLabel)]]" hidden$="[[!loaded]]" style="background-image:[[backgroundImages_]];" disabled$="[[disabled]]" value="{{selectedValue::change}}"> @@ -33,7 +33,16 @@ </select> </template> <template is="dom-if" if="[[printerStatusFlagEnabled_]]"> - <div>print-preview-destination-select-cros</div> + <print-preview-destination-dropdown-cros id="dropdown" + value="[[destination]]" hidden$="[[!loaded]]" + item-list="[[recentDestinationList]]" + pdf-destination-key="[[pdfDestinationKey_]]" + drive-destination-key="[[driveDestinationKey]]" + no-destinations="[[noDestinations]]" + pdf-printer-disabled="[[pdfPrinterDisabled]]" + destination-icon="[[destinationIcon_]]" disabled="[[disabled]]" + on-dropdown-value-selected="onDropdownValueSelected_"> + </print-preview-destination-dropdown-cros> </template> </div> </print-preview-settings-section> diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_select_cros.js b/chromium/chrome/browser/resources/print_preview/ui/destination_select_cros.js index f76ac017631..9eab3a242b4 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/destination_select_cros.js +++ b/chromium/chrome/browser/resources/print_preview/ui/destination_select_cros.js @@ -7,22 +7,46 @@ import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import 'chrome://resources/cr_elements/md_select_css.m.js'; import 'chrome://resources/js/util.m.js'; import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js'; +import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import 'chrome://resources/polymer/v3_0/iron-meta/iron-meta.js'; +import './destination_dropdown_cros.js'; import './destination_select_css.js'; import './icons.js'; import './print_preview_shared_css.js'; import './throbber_css.js'; import '../strings.m.js'; +import {assert} from 'chrome://resources/js/assert.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {Base, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {Destination, DestinationOrigin, PDF_DESTINATION_KEY, RecentDestination} from '../data/destination.js'; +import {CloudOrigins, Destination, DestinationOrigin, PDF_DESTINATION_KEY, RecentDestination} from '../data/destination.js'; +import {PrinterStatus, PrinterStatusReason, PrinterStatusSeverity} from '../data/printer_status_cros.js'; +import {NativeLayer, NativeLayerImpl} from '../native_layer.js'; import {getSelectDropdownBackground} from '../print_preview_utils.js'; import {SelectBehavior} from './select_behavior.js'; +/** @const {!Map<!PrinterStatusReason, string>} */ +const ERROR_STRING_KEY_MAP = new Map([ + [PrinterStatusReason.CONNECTING_TO_DEVICE, 'printerStatusConnectingToDevice'], + [PrinterStatusReason.DEVICE_ERROR, 'printerStatusDeviceError'], + [PrinterStatusReason.DOOR_OPEN, 'printerStatusDoorOpen'], + [PrinterStatusReason.LOW_ON_INK, 'printerStatusLowOnInk'], + [PrinterStatusReason.LOW_ON_PAPER, 'printerStatusLowOnPaper'], + [PrinterStatusReason.OUT_OF_INK, 'printerStatusOutOfInk'], + [PrinterStatusReason.OUT_OF_PAPER, 'printerStatusOutOfPaper'], + [PrinterStatusReason.OUTPUT_ALMOST_FULL, 'printerStatusOutputAlmostFull'], + [PrinterStatusReason.OUTPUT_FULL, 'printerStatusOutputFull'], + [PrinterStatusReason.PAPER_JAM, 'printerStatusPaperJam'], + [PrinterStatusReason.PAUSED, 'printerStatusPaused'], + [PrinterStatusReason.PRINTER_QUEUE_FULL, 'printerStatusPrinterQueueFull'], + [PrinterStatusReason.PRINTER_UNREACHABLE, 'printerStatusPrinterUnreachable'], + [PrinterStatusReason.STOPPED, 'printerStatusStopped'], + [PrinterStatusReason.TRAY_MISSING, 'printerStatusTrayMissing'], +]); + Polymer({ is: 'print-preview-destination-select-cros', @@ -36,7 +60,11 @@ Polymer({ dark: Boolean, /** @type {!Destination} */ - destination: Object, + destination: { + type: Object, + observer: 'updateStatusText_', + }, + disabled: Boolean, @@ -49,7 +77,10 @@ Polymer({ pdfPrinterDisabled: Boolean, /** @type {!Array<!Destination>} */ - recentDestinationList: Array, + recentDestinationList: { + type: Array, + observer: 'onRecentDestinationListChanged_', + }, /** @private {string} */ pdfDestinationKey_: { @@ -57,17 +88,20 @@ Polymer({ value: PDF_DESTINATION_KEY, }, + /** @private */ + statusText_: String, + /** @private {string} */ - statusText_: { + backgroundImages_: { type: String, - computed: 'computeStatusText_(destination)', + computed: + 'computeBackgroundImages_(destinationIcon_, dark, noDestinations)', }, /** @private {string} */ - backgroundImages_: { + destinationIcon_: { type: String, - computed: - 'computeBackgroundImages_(selectedValue, destination, noDestinations, dark)', + computed: 'computeDestinationIcon_(selectedValue, destination)', }, /** @private */ @@ -78,14 +112,32 @@ Polymer({ }, readOnly: true, }, + + /** + * The key for this map is a destination.id and the value is a + * destination.key. This map is needed to track which destinations have had + * statuses requested while also giving quick look up of destination id to + * the corresponding destination key. + * @private {!Map<string, string>} + */ + statusRequestedMap_: Map, }, /** @private {!IronMetaElement} */ meta_: /** @type {!IronMetaElement} */ ( Base.create('iron-meta', {type: 'iconset'})), + /** @override */ + attached() { + if (!this.printerStatusFlagEnabled_) { + return; + } + + this.statusRequestedMap_ = new Map(); + }, + focus() { - this.$$('.md-select').focus(); + this.$$('#dropdown').focus(); }, /** Sets the select to the current value of |destination|. */ @@ -100,7 +152,7 @@ Polymer({ * @return {string} The iconset and icon for the current selection. * @private */ - getDestinationIcon_() { + computeDestinationIcon_() { if (!this.selectedValue) { return ''; } @@ -140,8 +192,7 @@ Polymer({ * @private */ computeBackgroundImages_() { - const icon = this.getDestinationIcon_(); - if (!icon) { + if (!this.destinationIcon_) { return ''; } @@ -149,7 +200,7 @@ Polymer({ if (this.noDestinations) { iconSetAndIcon = ['cr', 'error']; } - iconSetAndIcon = iconSetAndIcon || icon.split(':'); + iconSetAndIcon = iconSetAndIcon || this.destinationIcon_.split(':'); const iconset = /** @type {!IronIconsetSvgElement} */ ( this.meta_.byKey(iconSetAndIcon[0])); return getSelectDropdownBackground(iconset, iconSetAndIcon[1], this); @@ -160,17 +211,179 @@ Polymer({ }, /** - * @return {string} The connection status text to display. + * @param {!Event} e * @private */ - computeStatusText_() { + onDropdownValueSelected_(e) { + assert(this.printerStatusFlagEnabled_); + + const selectedItem = e.detail; + if (!selectedItem || selectedItem.value === this.destination.key) { + return; + } + + this.fire('selected-option-change', selectedItem.value); + }, + + /** + * Send a printer status request for any new destination in the dropdown. + * @private + */ + onRecentDestinationListChanged_() { + if (!this.printerStatusFlagEnabled_) { + return; + } + + for (const destination of this.recentDestinationList) { + if (destination.origin !== DestinationOrigin.CROS || + this.statusRequestedMap_.has(destination.id)) { + continue; + } + + NativeLayerImpl.getInstance() + .requestPrinterStatusUpdate(destination.id) + .then(status => this.onPrinterStatusReceived_(status)); + this.statusRequestedMap_.set(destination.id, destination.key); + } + }, + + /** + * Check if the printer in |printerStatus| is currently in the dropdown. + * Update its status icon if it's present. + * @param {!PrinterStatus} printerStatus + * @private + */ + onPrinterStatusReceived_(printerStatus) { + assert(this.printerStatusFlagEnabled_); + if (!printerStatus.printerId) { + return; + } + + const destinationKey = + this.statusRequestedMap_.get(printerStatus.printerId); + if (!destinationKey) { + return; + } + + const indexFound = this.recentDestinationList.findIndex(destination => { + return destination.id === printerStatus.printerId && + destination.origin === DestinationOrigin.CROS; + }); + if (indexFound === -1) { + return; + } + + const statusReason = this.getStatusReasonFromPrinterStatus_(printerStatus); + if (!statusReason) { + return; + } + + + this.recentDestinationList[indexFound].printerStatusReason = statusReason; + // Set the new printer status reason then use notifyPath to trigger the + // dropdown printer status icons to recalculate their badge color. + this.notifyPath(`recentDestinationList.${indexFound}.printerStatusReason`); + + // Update the status text if this printer status is for the + // currently selected printer. + if (this.destination && this.destination.key === destinationKey) { + this.updateStatusText_(); + } + }, + + /** + * A |printerStatus| can have multiple status reasons so this function's + * responsibility is to determine which status reason is most relevant to + * surface to the user. Any status reason with a severity of WARNING or ERROR + * will get highest precedence since this usually means the printer is in a + * bad state. NO_ERROR status reason is the next highest precedence so the + * printer can be shown as available whenever possible. + * @param {!PrinterStatus} printerStatus + * @return {!PrinterStatusReason} Status reason extracted from + * |printerStatus|. + * @private + */ + getStatusReasonFromPrinterStatus_(printerStatus) { + assert(this.printerStatusFlagEnabled_); + + if (!printerStatus.printerId) { + return PrinterStatusReason.UNKNOWN_REASON; + } + + let seenNoErrorReason = false; + for (const statusReason of printerStatus.statusReasons) { + const reason = statusReason.reason; + const severity = statusReason.severity; + + if (reason !== PrinterStatusReason.UNKNOWN_REASON && + (severity === PrinterStatusSeverity.WARNING || + severity === PrinterStatusSeverity.ERROR)) { + return reason; + } + + if (reason === PrinterStatusReason.NO_ERROR) { + seenNoErrorReason = true; + } + } + return seenNoErrorReason ? PrinterStatusReason.NO_ERROR : + PrinterStatusReason.UNKNOWN_REASON; + }, + + /** + * Check the current destination for an error status then set |statusText_| + * appropriately. If no error status exists, unset |statusText_|. + * @private + */ + updateStatusText_: function() { // |destination| can be either undefined, or null here. if (!this.destination) { - return ''; + this.statusText_ = ''; + return; + } + + // Cloudprint destinations contain their own status text. + if (CloudOrigins.some(origin => origin === this.destination.origin)) { + this.statusText_ = this.destination.shouldShowInvalidCertificateError ? + this.i18n('noLongerSupportedFragment') : + this.destination.connectionStatusText; + return; } - return this.destination.shouldShowInvalidCertificateError ? - this.i18n('noLongerSupportedFragment') : - this.destination.connectionStatusText; + // Only when the flag is enabled do we need to fetch a local printer status + // error string. + if (!this.printerStatusFlagEnabled_) { + this.statusText_ = ''; + return; + } + + const printerStatusReason = this.destination.printerStatusReason; + if (!printerStatusReason || + printerStatusReason === PrinterStatusReason.NO_ERROR || + printerStatusReason === PrinterStatusReason.UNKNOWN_REASON) { + this.statusText_ = ''; + return; + } + + this.statusText_ = this.getErrorString_(printerStatusReason); + }, + + /** + * @param {!PrinterStatusReason} printerStatusReason + * @return {!string} + * @private + */ + getErrorString_: function(printerStatusReason) { + const errorTextKey = ERROR_STRING_KEY_MAP.get(printerStatusReason); + return errorTextKey ? + this.i18n(errorTextKey, this.destination.displayName) : + ''; + }, + + /** + * @return {!boolean} + * @private + */ + shouldShowStatus_: function() { + return !!this.statusText_; }, }); diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_settings.js b/chromium/chrome/browser/resources/print_preview/ui/destination_settings.js index f7259dbcfd0..4dce6653ae7 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/destination_settings.js +++ b/chromium/chrome/browser/resources/print_preview/ui/destination_settings.js @@ -66,7 +66,7 @@ Polymer({ value: null, }, - /** @private {!DestinationState} */ + /** @type {!DestinationState} */ destinationState: { type: Number, notify: true, @@ -527,6 +527,11 @@ Polymer({ }); }, + /** @return {!DestinationStore} */ + getDestinationStoreForTest() { + return assert(this.destinationStore_); + }, + // <if expr="chromeos"> /** * @param {!CustomEvent<string>} e Event containing the current destination's diff --git a/chromium/chrome/browser/resources/print_preview/ui/header.js b/chromium/chrome/browser/resources/print_preview/ui/header.js index 3848934ecb3..e441b03788d 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/header.js +++ b/chromium/chrome/browser/resources/print_preview/ui/header.js @@ -9,6 +9,7 @@ import './print_preview_vars_css.js'; import '../strings.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination} from '../data/destination.js'; @@ -40,12 +41,13 @@ Polymer({ sheetCount: Number, /** @private {?string} */ - summary_: { - type: String, - computed: 'computeSummary_(sheetCount, state, destination.id)', - }, + summary_: String, }, + observers: [ + 'updateSummary_(sheetCount, state, destination.id)', + ], + /** * @return {boolean} * @private @@ -56,21 +58,22 @@ Polymer({ this.destination.id === Destination.GooglePromotedId.DOCS); }, - /** - * @return {?string} - * @private - */ - computeSummary_() { + /** @private */ + updateSummary_() { switch (this.state) { case (State.PRINTING): - return loadTimeData.getString( + this.summary_ = loadTimeData.getString( this.isPdfOrDrive_() ? 'saving' : 'printing'); + break; case (State.READY): - return this.getSheetsSummary_(); + this.updateSheetsSummary_(); + break; case (State.FATAL_ERROR): - return this.getErrorMessage_(); + this.summary_ = this.getErrorMessage_(); + break; default: - return null; + this.summary_ = null; + break; } }, @@ -89,21 +92,19 @@ Polymer({ } }, - /** - * @return {string} - * @private - */ - getSheetsSummary_() { + /** @private */ + updateSheetsSummary_() { if (this.sheetCount === 0) { - return ''; + this.summary_ = ''; + return; } - const pageOrSheets = this.isPdfOrDrive_() ? 'Page' : 'Sheets'; - const singularOrPlural = this.sheetCount > 1 ? 'Plural' : 'Singular'; - const label = loadTimeData.getString( - `printPreview${pageOrSheets}Label${singularOrPlural}`); - return loadTimeData.getStringF( - 'printPreviewSummaryFormatShort', this.sheetCount.toLocaleString(), - label); + const pageOrSheet = this.isPdfOrDrive_() ? 'Page' : 'Sheet'; + PluralStringProxyImpl.getInstance() + .getPluralString( + `printPreview${pageOrSheet}SummaryLabel`, this.sheetCount) + .then(label => { + this.summary_ = label; + }); }, }); diff --git a/chromium/chrome/browser/resources/print_preview/ui/link_container.html b/chromium/chrome/browser/resources/print_preview/ui/link_container.html index 6ada90e22fa..9c483864f6c 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/link_container.html +++ b/chromium/chrome/browser/resources/print_preview/ui/link_container.html @@ -42,7 +42,7 @@ } .link:not([actionable]) .label { - @apply --print-preview-disabled-label; + opacity: var(--cr-disabled-opacity); } </style> <div class="link" id="systemDialogLink" diff --git a/chromium/chrome/browser/resources/print_preview/ui/more_settings.html b/chromium/chrome/browser/resources/print_preview/ui/more_settings.html index d63ce664e66..13c6d2c7678 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/more_settings.html +++ b/chromium/chrome/browser/resources/print_preview/ui/more_settings.html @@ -33,7 +33,7 @@ } :host([disabled]) #label { - @apply --print-preview-disabled-label; + opacity: var(--cr-disabled-opacity); } </style> <div on-click="toggleExpandButton_" actionable> diff --git a/chromium/chrome/browser/resources/print_preview/ui/preview_area.js b/chromium/chrome/browser/resources/print_preview/ui/preview_area.js index e75d9bffbf7..feb0ebf3849 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/preview_area.js +++ b/chromium/chrome/browser/resources/print_preview/ui/preview_area.js @@ -25,7 +25,7 @@ import {PrintableArea} from '../data/printable_area.js'; import {ScalingType} from '../data/scaling.js'; import {Size} from '../data/size.js'; import {Error, State} from '../data/state.js'; -import {NativeLayer} from '../native_layer.js'; +import {NativeLayer, NativeLayerImpl} from '../native_layer.js'; import {areRangesEqual} from '../print_preview_utils.js'; import {MARGIN_KEY_MAP} from './margin_control_container.js'; @@ -140,7 +140,7 @@ Polymer({ /** @override */ attached() { - this.nativeLayer_ = NativeLayer.getInstance(); + this.nativeLayer_ = NativeLayerImpl.getInstance(); this.addWebUIListener( 'page-preview-ready', this.onPagePreviewReady_.bind(this)); diff --git a/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.html b/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.html index 816b95996fe..6ecd94cd733 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.html +++ b/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.html @@ -50,7 +50,7 @@ on-search="onSearchTermSearch" on-input="onSearchTermInput" aria-label$="[[label]]" placeholder="[[label]]" autofocus="[[autofocus]]" spellcheck="false"> - <div slot="prefix" id="icon" class="cr-icon icon-search" alt=""></div> + <div slot="inline-prefix" id="icon" class="cr-icon icon-search" alt=""></div> <cr-icon-button id="clearSearch" class="icon-cancel" hidden$="[[!hasSearchText]]" slot="suffix" on-click="onClearClick_" title="[[clearLabel]]"> diff --git a/chromium/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html b/chromium/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html index d476823e7ec..2208774d52e 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html +++ b/chromium/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html @@ -8,10 +8,6 @@ --print-preview-settings-border: 1px solid var(--google-grey-200); --print-preview-dialog-margin: 34px; - --print-preview-disabled-label: { - color: var(--paper-grey-600); - opacity: .65; - } --cr-form-field-label-height: initial; --cr-form-field-label-line-height: .75rem; --destination-item-height: 32px; diff --git a/chromium/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.html b/chromium/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.html new file mode 100644 index 00000000000..450956a6557 --- /dev/null +++ b/chromium/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.html @@ -0,0 +1,67 @@ +<style include="cr-shared-style"> + div { + display: inline; + position: relative; + } + + .badge { + border-radius: 50%; + display: inline-block; + position: absolute; + --status-badge-radius: 8px; + --background-badge-radius: 12px; + --background-badge-left: 12px; + --background-badge-top: 6px; + } + + :host-context([dir='rtl']) .badge { + --background-badge-left: -4px; + } + + #status-badge { + height: var(--status-badge-radius); + left: calc(var(--background-badge-left) + (var(--background-badge-radius) - var(--status-badge-radius))/2); + top: calc(var(--background-badge-top) + (var(--background-badge-radius) - var(--status-badge-radius))/2); + width: var(--status-badge-radius); + } + + :host-context([state='0']) #status-badge { + background-color: var(--google-green-700); + } + + :host-context([state='1']) #status-badge { + background-color: var(--google-red-600); + } + + :host-context([state='2']) #status-badge { + background-color: var(--google-grey-500); + } + + :host-context([dir='rtl']) #status-badge { + right: calc(var(--background-badge-left) + (var(--background-badge-radius) - var(--status-badge-radius))/2); + } + + #background-badge { + height: var(--background-badge-radius); + left: var(--background-badge-left); + top: var(--background-badge-top); + width: var(--background-badge-radius); + } + + :host-context([background='grey']) #background-badge { + background-color: var(--google-grey-refresh-100); + } + + :host-context([background='white']) #background-badge { + background-color: white; + } + + :host-context([dir='rtl']) #background-badge { + right: var(--background-badge-left); + } +</style> +<div> + <iron-icon icon="print-preview:print"></iron-icon> + <span id="background-badge" class="badge"></span> + <span id="status-badge" class="badge"></span> +</div> diff --git a/chromium/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.js b/chromium/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.js new file mode 100644 index 00000000000..3ae2dc8a7de --- /dev/null +++ b/chromium/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.js @@ -0,0 +1,40 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/shared_vars_css.m.js'; +import './icons.js'; + +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +/** + * Enumeration giving a local Chrome OS printer 3 different state possibilities + * depending on its current status. + * @enum {number} + */ +export const PrinterState = { + GOOD: 0, + ERROR: 1, + UNKNOWN: 2, +}; + +Polymer({ + is: 'printer-status-icon-cros', + + properties: { + /** Determines color of the background badge. */ + background: String, + + /** + * State of the associated printer. Determines color of the status badge. + * @type {!PrinterState} + */ + state: { + type: Number, + reflectToAttribute: true, + } + }, + + _template: html`{__html_template__}`, + +}); diff --git a/chromium/chrome/browser/resources/print_preview/ui/select_behavior.js b/chromium/chrome/browser/resources/print_preview/ui/select_behavior.js index 4e21bb4d903..fbc6df96b58 100644 --- a/chromium/chrome/browser/resources/print_preview/ui/select_behavior.js +++ b/chromium/chrome/browser/resources/print_preview/ui/select_behavior.js @@ -31,10 +31,11 @@ export const SelectBehavior = { } this.debounce('select-change', () => { - this.onProcessSelectChange(this.selectedValue); - - // For testing only - this.fire('process-select-change'); + if (this.isConnected) { + this.onProcessSelectChange(this.selectedValue); + // For testing only + this.fire('process-select-change'); + } }, 100); }, diff --git a/chromium/chrome/browser/resources/quota_internals/event_handler.js b/chromium/chrome/browser/resources/quota_internals/event_handler.js index 6d0e7ddd9d3..d8c8b787ab3 100644 --- a/chromium/chrome/browser/resources/quota_internals/event_handler.js +++ b/chromium/chrome/browser/resources/quota_internals/event_handler.js @@ -391,6 +391,22 @@ function handleStatistics(event) { } /** + * Event Handler for |cr.quota.onStoragePressureFlagUpdated|. + * |event.detail| contains a boolean representing whether or not to show + * the storage pressure UI. + * @param {!CustomEvent<!Object>} event StoragePressureFlagUpdated event. + */ +function handleStoragePressureFlagInfo(event) { + const data = event.detail; + $('storage-pressure-loading').hidden = true; + if (data.isStoragePressureEnabled) { + $('storage-pressure-outer').hidden = false; + } else { + $('storage-pressure-disabled').hidden = false; + } +} + +/** * Update description on 'tree-item-description' field with * selected item in tree view. */ @@ -490,6 +506,8 @@ function onLoad() { cr.quota.onPerOriginInfoUpdated.addEventListener( 'update', handlePerOriginInfo); cr.quota.onStatisticsUpdated.addEventListener('update', handleStatistics); + cr.quota.onStoragePressureFlagUpdated.addEventListener( + 'update', handleStoragePressureFlagInfo); cr.quota.requestInfo(); $('refresh-button').addEventListener('click', cr.quota.requestInfo, false); diff --git a/chromium/chrome/browser/resources/quota_internals/main.html b/chromium/chrome/browser/resources/quota_internals/main.html index 59d0a4bbb2d..c1f7fb6458f 100644 --- a/chromium/chrome/browser/resources/quota_internals/main.html +++ b/chromium/chrome/browser/resources/quota_internals/main.html @@ -56,16 +56,26 @@ found in the LICENSE file. <table> <tbody id="stat-entries" class="entries"></tbody> </table> - <h2>Test Storage Pressure Behavior</h2> - <div class="pressure"> - Origin to test: - <input id="storage-pressure-origin" - value="https://www.example.com"> - </div> - <div class="pressure"> - <button id="trigger-notification"> - Trigger Storage Pressure Notification - </button> + <div id="storage-pressure-section"> + <h2>Test Storage Pressure Behavior</h2> + <div id="storage-pressure-loading"> + Loading... + </div> + <div id="storage-pressure-outer" hidden> + <div class="pressure"> + Origin to test: + <input id="storage-pressure-origin" + value="https://www.example.com"> + </div> + <div class="pressure"> + <button id="trigger-notification"> + Trigger Storage Pressure Notification + </button> + </div> + </div> + <div id="storage-pressure-disabled" hidden> + Storage Pressure feature disabled. + </div> </div> </tabpanel> diff --git a/chromium/chrome/browser/resources/quota_internals/message_dispatcher.js b/chromium/chrome/browser/resources/quota_internals/message_dispatcher.js index 473ce67bfd7..25fa7ecf1bb 100644 --- a/chromium/chrome/browser/resources/quota_internals/message_dispatcher.js +++ b/chromium/chrome/browser/resources/quota_internals/message_dispatcher.js @@ -38,13 +38,15 @@ cr.define('cr.quota', function() { * * onGlobalInfoUpdated, * * onPerHostInfoUpdated, * * onPerOriginInfoUpdated, - * * onStatisticsUpdated. + * * onStatisticsUpdated, + * * onStoragePressureFlagUpdated. * @param {string} message Message label. Possible Values are: * * 'AvailableSpaceUpdated', * * 'GlobalInfoUpdated', * * 'PerHostInfoUpdated', * * 'PerOriginInfoUpdated', - * * 'StatisticsUpdated'. + * * 'StatisticsUpdated', + * * 'StoragePressureFlagUpdated'. * @param {Object} detail Message specific additional data. */ function messageHandler(message, detail) { @@ -65,6 +67,9 @@ cr.define('cr.quota', function() { case 'StatisticsUpdated': target = cr.quota.onStatisticsUpdated; break; + case 'StoragePressureFlagUpdated': + target = cr.quota.onStoragePressureFlagUpdated; + break; default: console.error('Unknown Message'); break; @@ -82,6 +87,7 @@ cr.define('cr.quota', function() { onPerHostInfoUpdated: new cr.EventTarget(), onPerOriginInfoUpdated: new cr.EventTarget(), onStatisticsUpdated: new cr.EventTarget(), + onStoragePressureFlagUpdated: new cr.EventTarget(), requestInfo: requestInfo, triggerStoragePressure: triggerStoragePressure, diff --git a/chromium/chrome/browser/resources/quota_internals/quota_internals_resources.grd b/chromium/chrome/browser/resources/quota_internals/quota_internals_resources.grd index c5b1cca697e..3694a9782c4 100644 --- a/chromium/chrome/browser/resources/quota_internals/quota_internals_resources.grd +++ b/chromium/chrome/browser/resources/quota_internals/quota_internals_resources.grd @@ -8,9 +8,9 @@ </outputs> <release seq="1"> <includes> - <include name="IDR_QUOTA_INTERNALS_MAIN_HTML" file="main.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip"/> - <include name="IDR_QUOTA_INTERNALS_EVENT_HANDLER_JS" file="event_handler.js" type="BINDATA" compress="gzip"/> - <include name="IDR_QUOTA_INTERNALS_MESSAGE_DISPATCHER_JS" file="message_dispatcher.js" type="BINDATA" compress="gzip"/> + <include name="IDR_QUOTA_INTERNALS_MAIN_HTML" file="main.html" flattenhtml="true" allowexternalscript="true" type="BINDATA"/> + <include name="IDR_QUOTA_INTERNALS_EVENT_HANDLER_JS" file="event_handler.js" type="BINDATA"/> + <include name="IDR_QUOTA_INTERNALS_MESSAGE_DISPATCHER_JS" file="message_dispatcher.js" type="BINDATA"/> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/settings/BUILD.gn b/chromium/chrome/browser/resources/settings/BUILD.gn index 4250f4fa750..a0a669d3b12 100644 --- a/chromium/chrome/browser/resources/settings/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/BUILD.gn @@ -71,6 +71,7 @@ group("closure_compile") { "appearance_page:closure_compile", "controls:closure_compile", "languages_page:closure_compile", + "nearby_share_page:closure_compile", "people_page:closure_compile", "prefs:closure_compile", "privacy_page:closure_compile", @@ -148,6 +149,7 @@ group("closure_compile_module") { "controls:closure_compile_module", "downloads_page:closure_compile_module", "languages_page:closure_compile_module", + "nearby_share_page:closure_compile_module", "on_startup_page:closure_compile_module", "people_page:closure_compile_module", "prefs:closure_compile_module", @@ -196,7 +198,6 @@ js_type_check("closure_compile_local_module") { ":metrics_browser_proxy", ":open_window_proxy", ":page_visibility", - ":plural_string_proxy", ":route", ":router.m", ":search_settings.m", @@ -213,6 +214,8 @@ js_library("settings") { ":metrics_browser_proxy", ":open_window_proxy", "about_page:about_page_browser_proxy.m", + "autofill_page:multi_store_exception_entry", + "autofill_page:multi_store_password_ui_entry", "autofill_page:password_manager_proxy", "people_page:sync_browser_proxy.m", "privacy_page:privacy_page_browser_proxy.m", @@ -278,10 +281,6 @@ js_library("page_visibility") { deps = [ "//ui/webui/resources/js:load_time_data.m" ] } -js_library("plural_string_proxy") { - deps = [ "//ui/webui/resources/js:cr.m" ] -} - js_library("route") { deps = [ ":page_visibility", diff --git a/chromium/chrome/browser/resources/settings/autofill_page/BUILD.gn b/chromium/chrome/browser/resources/settings/autofill_page/BUILD.gn index f48d5203d74..f74ab14757f 100644 --- a/chromium/chrome/browser/resources/settings/autofill_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/autofill_page/BUILD.gn @@ -16,6 +16,11 @@ js_type_check("closure_compile_module") { ":blocking_request_manager", ":credit_card_edit_dialog", ":credit_card_list_entry", + ":merge_exceptions_store_copies_behavior", + ":merge_passwords_store_copies_behavior", + ":multi_store_exception_entry", + ":multi_store_id_handler", + ":multi_store_password_ui_entry", ":password_check", ":password_check_behavior", ":password_check_edit_dialog", @@ -24,8 +29,12 @@ js_type_check("closure_compile_module") { ":password_edit_dialog", ":password_list_item", ":password_manager_proxy", + ":password_move_to_account_dialog", ":password_remove_confirmation_dialog", + ":password_remove_dialog", + ":passwords_device_section", ":passwords_export_dialog", + ":passwords_list_handler", ":passwords_section", ":payments_list", ":payments_section", @@ -100,9 +109,8 @@ js_library("password_check") { ":blocking_request_manager", ":password_check_behavior", ":password_manager_proxy", - "..:plural_string_proxy", - "../prefs:prefs_behavior.m", "..:route", + "../prefs:prefs_behavior.m", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:i18n_behavior.m", @@ -112,7 +120,7 @@ js_library("password_check") { js_library("password_check_behavior") { deps = [ ":password_manager_proxy", - "..:plural_string_proxy", + "//ui/webui/resources/js:plural_string_proxy", ] externs_list = [ "$externs_path/passwords_private.js" ] } @@ -152,6 +160,29 @@ js_library("password_edit_dialog") { ] } +js_library("multi_store_password_ui_entry") { + sources = [ "multi_store_password_ui_entry.js" ] + deps = [ + ":multi_store_id_handler", + ":password_manager_proxy", + "//ui/webui/resources/js:assert.m", + ] +} + +js_library("multi_store_exception_entry") { + sources = [ "multi_store_exception_entry.js" ] + deps = [ + ":multi_store_id_handler", + ":password_manager_proxy", + "//ui/webui/resources/js:assert.m", + ] +} + +js_library("multi_store_id_handler") { + sources = [ "multi_store_id_handler.js" ] + deps = [ "//ui/webui/resources/js:assert.m" ] +} + js_library("password_remove_confirmation_dialog") { deps = [ ":password_manager_proxy", @@ -171,9 +202,50 @@ js_library("password_list_item") { ] } +js_library("passwords_list_handler") { + deps = [ + ":blocking_request_manager", + ":password_edit_dialog", + ":password_manager_proxy", + ":password_move_to_account_dialog", + ":password_remove_dialog", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m", + "//ui/webui/resources/cr_elements/cr_button:cr_button.m", + "//ui/webui/resources/cr_elements/cr_toast:cr_toast.m", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:i18n_behavior.m", + "//ui/webui/resources/js/cr/ui:focus_without_ink.m", + ] +} + +js_library("password_move_to_account_dialog") { + deps = [ + ":multi_store_password_ui_entry", + ":password_manager_proxy", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_button:cr_button.m", + "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:i18n_behavior.m", + ] +} + js_library("password_manager_proxy") { deps = [ "//ui/webui/resources/js:cr.m" ] - externs_list = [ "$externs_path/passwords_private.js" ] + externs_list = + chrome_extension_public_externs + [ "$externs_path/passwords_private.js" ] +} + +js_library("password_remove_dialog") { + deps = [ + ":multi_store_password_ui_entry", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_button:cr_button.m", + "//ui/webui/resources/cr_elements/cr_checkbox:cr_checkbox.m", + "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", + "//ui/webui/resources/js:assert.m", + ] } js_library("passwords_export_dialog") { @@ -185,21 +257,23 @@ js_library("passwords_export_dialog") { js_library("passwords_section") { deps = [ - ":password_edit_dialog", + ":merge_exceptions_store_copies_behavior", + ":merge_passwords_store_copies_behavior", + ":multi_store_exception_entry", + ":multi_store_password_ui_entry", ":password_list_item", ":password_manager_proxy", + ":passwords_list_handler", "..:global_scroll_target_behavior.m", - "..:plural_string_proxy", "..:route", + "../people_page:profile_info_browser_proxy.m", "../people_page:sync_browser_proxy.m", "../prefs:prefs_behavior.m", "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer", "//third_party/polymer/v3_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior", "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m", - "//ui/webui/resources/cr_elements/cr_toast:cr_toast_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:i18n_behavior.m", - "//ui/webui/resources/js:list_property_update_behavior.m", "//ui/webui/resources/js:util.m", "//ui/webui/resources/js:web_ui_listener_behavior.m", "//ui/webui/resources/js/cr/ui:focus_without_ink.m", @@ -210,6 +284,25 @@ js_library("passwords_section") { ] } +js_library("passwords_device_section") { + deps = [ + ":merge_passwords_store_copies_behavior", + ":multi_store_password_ui_entry", + ":password_list_item", + ":password_manager_proxy", + ":passwords_list_handler", + "..:i18n_setup", + "..:open_window_proxy", + "..:route", + "../people_page:profile_info_browser_proxy.m", + "//third_party/polymer/v3_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:icon.m", + "//ui/webui/resources/js:util.m", + "//ui/webui/resources/js:web_ui_listener_behavior.m", + ] +} + js_library("payments_list") { deps = [ ":credit_card_list_entry", @@ -240,11 +333,29 @@ js_library("payments_section") { js_library("show_password_behavior") { deps = [ ":blocking_request_manager", + ":multi_store_password_ui_entry", ":password_manager_proxy", ] externs_list = [ "$externs_path/passwords_private.js" ] } +js_library("merge_passwords_store_copies_behavior") { + deps = [ + ":multi_store_password_ui_entry", + ":password_manager_proxy", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:list_property_update_behavior.m", + ] +} + +js_library("merge_exceptions_store_copies_behavior") { + deps = [ + ":multi_store_exception_entry", + ":password_manager_proxy", + "//ui/webui/resources/js:assert.m", + ] +} + js_library("upi_id_list_entry") { deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", @@ -257,6 +368,7 @@ html_to_js("web_components") { "address_edit_dialog.js", "autofill_page.js", "autofill_section.js", + "passwords_list_handler.js", "credit_card_edit_dialog.js", "credit_card_list_entry.js", "password_check_edit_dialog.js", @@ -264,10 +376,13 @@ html_to_js("web_components") { "password_check_list_item.js", "password_check.js", "password_edit_dialog.js", + "password_remove_dialog.js", "password_list_item.js", + "password_move_to_account_dialog.js", "password_remove_confirmation_dialog.js", "passwords_export_dialog.js", "passwords_section.js", + "passwords_device_section.js", "passwords_shared_css.js", "payments_list.js", "payments_section.js", diff --git a/chromium/chrome/browser/resources/settings/chromeos/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/BUILD.gn index 2e345985162..9a49bb22976 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/BUILD.gn @@ -8,11 +8,16 @@ import("//tools/grit/grit_rule.gni") import("//ui/webui/resources/tools/js_modulizer.gni") import("//ui/webui/webui_features.gni") import("../../optimize_webui.gni") +import("./os_settings.gni") if (optimize_webui) { settings_pak_file = "os_settings_resources.pak" unpak_folder = "os_settings_resources.unpak" + # Put v3 unpacked files in a separate folder, to avoid a possible race + # between v2 and v3 build targets writing files to the same location. + unpak_folder_v3 = "os_settings_resources_v3.unpak" + optimize_webui("build") { host = "os-settings" html_in_files = [ @@ -34,9 +39,7 @@ if (optimize_webui) { "chrome://resources/css/cros_colors.generated.css", "chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom.html", "chrome://os-settings/app-management/app_management.mojom-lite.js", - "chrome://os-settings/app-management/bitmap.mojom-lite.js", "chrome://os-settings/app-management/file_path.mojom-lite.js", - "chrome://os-settings/app-management/image_info.mojom-lite.js", "chrome://os-settings/app-management/image.mojom-lite.js", "chrome://os-settings/app-management/types.mojom-lite.js", "chrome://os-settings/constants/routes.mojom-lite.js", @@ -47,14 +50,70 @@ if (optimize_webui) { "chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom.html", "chrome://resources/mojo/mojo/public/mojom/base/string16.mojom.html", "chrome://resources/mojo/mojo/public/mojom/base/time.mojom.html", + "chrome://resources/mojo/skia/public/mojom/bitmap.mojom-lite.js", + "chrome://resources/mojo/skia/public/mojom/image_info.mojom-lite.js", + "chrome://resources/mojo/url/mojom/url.mojom-lite.js", ] deps = [ ":unpak" ] } + optimize_webui("build_polymer3") { + host = "os-settings" + input = rebase_path("$target_gen_dir/$unpak_folder_v3", root_build_dir) + js_out_files = [ "os_settings.rollup.js" ] + js_module_in_files = [ "chromeos/os_settings.js" ] + + deps = [ + ":unpak_v3", + "../../../../../ui/webui/resources:modulize", + ] + excludes = [ + "chrome://resources/js/cr.m.js", + "chrome://resources/css/cros_colors.generated.css", + "chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js", + "chrome://resources/mojo/url/mojom/url.mojom-lite.js", + "app-management/app_management.mojom-lite.js", + "app-management/bitmap.mojom-lite.js", + "app-management/file_path.mojom-lite.js", + "app-management/image_info.mojom-lite.js", + "app-management/image.mojom-lite.js", + "app-management/types.mojom-lite.js", + "constants/routes.mojom-lite.js", + "constants/setting.mojom-lite.js", + "search/search.mojom-lite.js", + "search/search_result_icon.mojom-lite.js", + "search/user_action_recorder.mojom-lite.js", + ] + } + + unpak_excludes = [ + "../../ui/webui/settings/chromeos/constants/routes.mojom-lite.js", + "../../ui/webui/settings/chromeos/constants/setting.mojom-lite.js", + "../../../../mojo/public/mojom/base/file_path.mojom-lite.js", + "../../../../ui/gfx/image/mojom/image.mojom-lite.js", + "../../../../url/mojom/url.mojom-lite.js", + "../../ui/webui/app_management/app_management.mojom-lite.js", + "../../../../components/services/app_service/public/mojom/types.mojom-lite.js", + "../../ui/webui/settings/chromeos/search/search.mojom-lite.js", + "../../ui/webui/settings/chromeos/search/search_result_icon.mojom-lite.js", + "../../ui/webui/settings/chromeos/search/user_action_recorder.mojom-lite.js", + ] + + unpak("unpak_v3") { + pak_file = settings_pak_file + out_folder = unpak_folder_v3 + pak_base_dir = "../" + excludes = unpak_excludes + + deps = [ ":flattened_resources" ] + } + unpak("unpak") { pak_file = settings_pak_file out_folder = unpak_folder + pak_base_dir = "../" + excludes = unpak_excludes deps = [ ":flattened_resources" ] } @@ -174,13 +233,15 @@ group("closure_compile_module") { # TODO: Uncomment as the Polymer3 migration makes progress. #":closure_compile_local_module", #"ambient_mode_page:closure_compile_module", - #"bluetooth_page:closure_compile_module", + "bluetooth_page:closure_compile_module", + #"crostini_page:closure_compile_module", #"date_time_page:closure_compile_module", #"device_page:closure_compile_module", #"google_assistant_page:closure_compile_module", #"internet_page:closure_compile_module", - #"localized_link:closure_compile_module", + "localized_link:closure_compile_module", + #"multidevice_page:closure_compile_module", #"os_a11y_page:closure_compile_module", #"os_about_page:closure_compile_module", @@ -191,7 +252,8 @@ group("closure_compile_module") { #"os_people_page:closure_compile_module", #"os_printing_page:closure_compile_module", #"os_privacy_page:closure_compile_module", - #"os_reset_page:closure_compile_module", + "os_reset_page:closure_compile_module", + #"os_search_page:closure_compile_module", #"os_settings_main:closure_compile_module", #"os_settings_menu:closure_compile_module", @@ -204,28 +266,28 @@ group("closure_compile_module") { ] } -# TODO: Uncomment as the Polymer3 migration makes progress. -#js_type_check("closure_compile_local_module") { -# is_polymer3 = true -# deps = [ -# ":metrics_recorder.m", -# ":os_icons.m", -# ":os_page_visibility.m", -# ":os_route.m", -# ":os_settings.m", -# ":os_settings_icons_css.m", -# ":os_settings_routes.m", -# ":route_origin_behavior.m", -# ":search_handler.m", -# ] -#} +js_type_check("closure_compile_local_module") { + is_polymer3 = true + deps = [ + ":metrics_recorder.m", + + # ":os_icons.m", + # ":os_page_visibility.m", + ":os_route.m", + + # ":os_settings.m", + # ":os_settings_icons_css.m", + ":os_settings_routes.m", + + # ":route_origin_behavior.m", + # ":search_handler.m", + ] +} js_library("metrics_recorder.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/metrics_recorder.m.js" ] - deps = [ - # TODO: Fill those in. - ] - extra_deps = [ ":metrics_recorder_module" ] + deps = [ "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings_js_library_for_compile" ] + extra_deps = [ ":modulize" ] } js_library("os_icons.m") { @@ -251,9 +313,13 @@ js_library("os_route.m") { "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_route.m.js", ] deps = [ - # TODO: Fill those in. + ":os_settings_routes.m", + "..:router.m", + "//chrome/browser/ui/webui/settings/chromeos/constants:mojom_js_library_for_compile", + "//ui/webui/resources/js:cr.m", + "//ui/webui/resources/js:load_time_data.m", ] - extra_deps = [ ":os_route_module" ] + extra_deps = [ ":modulize" ] } js_library("os_settings_icons_css.m") { @@ -266,9 +332,7 @@ js_library("os_settings_icons_css.m") { js_library("os_settings_routes.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_settings_routes.m.js" ] - deps = [ - # TODO: Fill those in. - ] + deps = [ "//ui/webui/resources/js:load_time_data.m" ] extra_deps = [ ":modulize" ] } @@ -323,19 +387,21 @@ group("polymer3_elements") { "personalization_page:polymer3_elements", # Local targets - ":metrics_recorder_module", ":modulize", ":os_icons_module", ":os_page_visibility_module", - ":os_route_module", ":os_settings_icons_css_module", - ] -} -polymer_modulizer("metrics_recorder") { - js_file = "metrics_recorder.js" - html_file = "metrics_recorder.html" - html_type = "dom-module" + # Shared with browser settings + "..:modulize", + "..:settings_shared_css_module", + "..:settings_vars_css_module", + "../nearby_share_page:polymer3_elements", + "../prefs:modulize", + "../prefs:prefs_module", + "../settings_page:settings_animated_pages_module", + "../settings_page:settings_subpage_module", + ] } polymer_modulizer("os_icons") { @@ -350,12 +416,6 @@ polymer_modulizer("os_page_visibility") { html_type = "dom-module" } -polymer_modulizer("os_route") { - js_file = "os_route.js" - html_file = "os_route.html" - html_type = "dom-module" -} - polymer_modulizer("os_settings_icons_css") { js_file = "os_settings_icons_css.m.js" html_file = "os_settings_icons_css.html" @@ -364,8 +424,11 @@ polymer_modulizer("os_settings_icons_css") { js_modulizer("modulize") { input_files = [ + "metrics_recorder.js", "os_settings_routes.js", "route_origin_behavior.js", "search_handler.js", + "os_route.js", ] + namespace_rewrites = os_settings_namespace_rewrites } diff --git a/chromium/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn index 3e19c60857f..71795b20191 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn @@ -8,31 +8,54 @@ js_type_check("closure_compile") { deps = [ ":ambient_mode_browser_proxy", ":ambient_mode_page", + ":ambient_mode_photos_page", + ":constants", ] } js_library("ambient_mode_browser_proxy") { - deps = [ "//ui/webui/resources/js:cr" ] + deps = [ + ":constants", + "//ui/webui/resources/js:cr", + ] externs_list = [ "$externs_path/chrome_send.js" ] } js_library("ambient_mode_page") { deps = [ ":ambient_mode_browser_proxy", + ":constants", + "..:os_route", + "../..:router", "../../prefs:prefs_behavior", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:i18n_behavior", - "//ui/webui/resources/js:load_time_data", "//ui/webui/resources/js:web_ui_listener_behavior", ] } +js_library("ambient_mode_photos_page") { + deps = [ + ":ambient_mode_browser_proxy", + ":constants", + "..:os_route", + "../..:router", + "//ui/webui/resources/js:cr", + "//ui/webui/resources/js:i18n_behavior", + "//ui/webui/resources/js:web_ui_listener_behavior", + ] +} + +js_library("constants") { +} + # TODO: Uncomment as the Polymer3 migration makes progress. #js_type_check("closure_compile_module") { # is_polymer3 = true # deps = [ # ":ambient_mode_browser_proxy.m", -# ":ambient_mode_page.m" +# ":ambient_mode_page.m", +# ":ambient_mode_photos_page.m", # ] #} @@ -52,11 +75,20 @@ js_library("ambient_mode_page.m") { extra_deps = [ ":ambient_mode_page_module" ] } +js_library("ambient_mode_photos_page.m") { + sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.m.js" ] + deps = [ + # TODO: Fill those in. + ] + extra_deps = [ ":ambient_mode_photos_page_module" ] +} + import("//tools/polymer/polymer.gni") group("polymer3_elements") { public_deps = [ ":ambient_mode_page_module", + ":ambient_mode_photos_page_module", ":modulize", ] } @@ -67,8 +99,17 @@ polymer_modulizer("ambient_mode_page") { html_type = "dom-module" } +polymer_modulizer("ambient_mode_photos_page") { + js_file = "ambient_mode_photos_page.js" + html_file = "ambient_mode_photos_page.html" + html_type = "dom-module" +} + import("//ui/webui/resources/tools/js_modulizer.gni") js_modulizer("modulize") { - input_files = [ "ambient_mode_browser_proxy.js" ] + input_files = [ + "ambient_mode_browser_proxy.js", + "constants.js", + ] } diff --git a/chromium/chrome/browser/resources/settings/chromeos/bluetooth_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/bluetooth_page/BUILD.gn index a3432524ed1..9d36108f851 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/bluetooth_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/bluetooth_page/BUILD.gn @@ -3,6 +3,8 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/polymer.gni") +import("../os_settings.gni") js_type_check("closure_compile") { deps = [ @@ -14,11 +16,11 @@ js_type_check("closure_compile") { js_library("bluetooth_page") { deps = [ - ":bluetooth_system_on_extensions", "..:os_route", "../..:router", "../../prefs:prefs_behavior", "../../settings_page:settings_animated_pages", + "//services/device/public/mojom:mojom_js_library_for_compile", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", ] @@ -34,20 +36,20 @@ js_library("bluetooth_page") { js_library("bluetooth_subpage") { deps = [ - ":bluetooth_system_on_extensions", "..:metrics_recorder", "..:os_route", "../..:router", - "//ui/webui/resources/cr_components/chromeos:bluetooth_dialog", + "//services/device/public/mojom:mojom_js_library_for_compile", + "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_dialog", "//ui/webui/resources/cr_elements:cr_scrollable_behavior", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", "//ui/webui/resources/js:list_property_update_behavior", ] - externs_list = [ - "$externs_path/bluetooth.js", - "$externs_path/bluetooth_private.js", - ] + externs_list = chrome_extension_public_externs + [ + "$externs_path/bluetooth.js", + "$externs_path/bluetooth_private.js", + ] extra_sources = [ "$interfaces_path/bluetooth_interface.js", "$interfaces_path/bluetooth_private_interface.js", @@ -56,7 +58,7 @@ js_library("bluetooth_subpage") { js_library("bluetooth_device_list_item") { deps = [ - ":bluetooth_system_on_extensions", + "//services/device/public/mojom:mojom_js_library_for_compile", "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu", "//ui/webui/resources/js:i18n_behavior", "//ui/webui/resources/js/cr/ui:focus_row_behavior", @@ -64,33 +66,42 @@ js_library("bluetooth_device_list_item") { externs_list = [ "$externs_path/bluetooth.js" ] } -js_library("bluetooth_system_on_extensions") { - sources = [] - deps = [ "//services/device/public/mojom:mojom_js_library_for_compile" ] +js_type_check("closure_compile_module") { + is_polymer3 = true + deps = [ + ":bluetooth_device_list_item.m", + ":bluetooth_page.m", + ":bluetooth_subpage.m", + ] } -# TODO: Uncomment as the Polymer3 migration makes progress. -#js_type_check("closure_compile_module") { -# is_polymer3 = true -# deps = [ -# ":bluetooth_device_list_item.m", -# ":bluetooth_page.m", -# ":bluetooth_subpage.m" -# ] -#} - js_library("bluetooth_device_list_item.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_device_list_item.m.js" ] deps = [ - # TODO: Fill those in. + "//services/device/public/mojom:mojom_js_library_for_compile", + "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m", + "//ui/webui/resources/js:i18n_behavior.m", + "//ui/webui/resources/js/cr/ui:focus_row_behavior.m", ] + externs_list = [ "$externs_path/bluetooth.js" ] extra_deps = [ ":bluetooth_device_list_item_module" ] } js_library("bluetooth_page.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page.m.js" ] deps = [ - # TODO: Fill those in. + ":bluetooth_subpage.m", + "..:os_route.m", + "../..:router.m", + "../../prefs:prefs_behavior.m", + "../../settings_page:settings_animated_pages.m", + "//services/device/public/mojom:mojom_js_library_for_compile", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:i18n_behavior.m", + ] + externs_list = [ + "$externs_path/bluetooth.js", + "$externs_path/bluetooth_private.js", ] extra_deps = [ ":bluetooth_page_module" ] } @@ -98,13 +109,24 @@ js_library("bluetooth_page.m") { js_library("bluetooth_subpage.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.m.js" ] deps = [ - # TODO: Fill those in. + "..:metrics_recorder.m", + "..:os_route.m", + "../..:router.m", + "//services/device/public/mojom:mojom_js_library_for_compile", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_dialog.m", + "//ui/webui/resources/cr_elements:cr_scrollable_behavior.m", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:i18n_behavior.m", + "//ui/webui/resources/js:list_property_update_behavior.m", + ] + externs_list = [ + "$externs_path/bluetooth.js", + "$externs_path/bluetooth_private.js", ] extra_deps = [ ":bluetooth_subpage_module" ] } -import("//tools/polymer/polymer.gni") - group("polymer3_elements") { public_deps = [ ":bluetooth_device_list_item_module", @@ -117,16 +139,25 @@ polymer_modulizer("bluetooth_device_list_item") { js_file = "bluetooth_device_list_item.js" html_file = "bluetooth_device_list_item.html" html_type = "dom-module" + migrated_imports = os_settings_migrated_imports + namespace_rewrites = os_settings_namespace_rewrites + auto_imports = os_settings_auto_imports } polymer_modulizer("bluetooth_page") { js_file = "bluetooth_page.js" html_file = "bluetooth_page.html" html_type = "dom-module" + migrated_imports = os_settings_migrated_imports + namespace_rewrites = os_settings_namespace_rewrites + auto_imports = os_settings_auto_imports } polymer_modulizer("bluetooth_subpage") { js_file = "bluetooth_subpage.js" html_file = "bluetooth_subpage.html" html_type = "dom-module" + migrated_imports = os_settings_migrated_imports + namespace_rewrites = os_settings_namespace_rewrites + auto_imports = os_settings_auto_imports } diff --git a/chromium/chrome/browser/resources/settings/chromeos/crostini_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/crostini_page/BUILD.gn index 8da221484d9..abf46959d3f 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/crostini_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/crostini_page/BUILD.gn @@ -12,6 +12,7 @@ js_type_check("closure_compile") { ":crostini_export_import", ":crostini_page", ":crostini_port_forwarding", + ":crostini_port_forwarding_add_port_dialog", ":crostini_shared_paths", ":crostini_shared_usb_devices", ":crostini_subpage", @@ -92,6 +93,14 @@ js_library("crostini_port_forwarding") { ] } +js_library("crostini_port_forwarding_add_port_dialog") { + deps = [ + ":crostini_browser_proxy", + "..:metrics_recorder", + "//ui/webui/resources/js:cr", + ] +} + js_library("crostini_subpage") { deps = [ ":crostini_browser_proxy", diff --git a/chromium/chrome/browser/resources/settings/chromeos/date_time_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/date_time_page/BUILD.gn index 4d73c447751..3bfa5759c96 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/date_time_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/date_time_page/BUILD.gn @@ -8,6 +8,7 @@ js_type_check("closure_compile") { deps = [ ":date_time_page", ":date_time_types", + ":timezone_browser_proxy", ":timezone_selector", ":timezone_subpage", ] @@ -17,7 +18,6 @@ js_library("date_time_page") { deps = [ ":date_time_types", ":timezone_selector", - ":timezone_subpage", "..:os_route", "../..:router", "../../prefs:prefs_behavior", @@ -33,6 +33,10 @@ js_library("date_time_types") { deps = [ "//ui/webui/resources/js:cr" ] } +js_library("timezone_browser_proxy") { + deps = [ "//ui/webui/resources/js:cr" ] +} + js_library("timezone_selector") { deps = [ ":date_time_types", @@ -46,6 +50,7 @@ js_library("timezone_selector") { js_library("timezone_subpage") { deps = [ ":date_time_types", + ":timezone_browser_proxy", ":timezone_selector", "../../prefs:prefs_behavior", "//ui/webui/resources/js:cr", @@ -58,6 +63,7 @@ js_library("timezone_subpage") { # deps = [ # ":date_time_page.m", # ":date_time_types.m", +# ":timezone_browser_proxy.m", # ":timezone_selector.m", # ":timezone_subpage.m" # ] @@ -79,6 +85,14 @@ js_library("date_time_types.m") { extra_deps = [ ":date_time_types_module" ] } +js_library("timezone_browser_proxy.m") { + sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/date_time_page/timezone_browser_proxy.m.js" ] + deps = [ + # TODO: Fill those in. + ] + extra_deps = [ ":modulize" ] +} + js_library("timezone_selector.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.m.js" ] deps = [ @@ -101,6 +115,7 @@ group("polymer3_elements") { public_deps = [ ":date_time_page_module", ":date_time_types_module", + ":modulize", ":timezone_selector_module", ":timezone_subpage_module", ] @@ -129,3 +144,9 @@ polymer_modulizer("timezone_subpage") { html_file = "timezone_subpage.html" html_type = "dom-module" } + +import("//ui/webui/resources/tools/js_modulizer.gni") + +js_modulizer("modulize") { + input_files = [ "timezone_browser_proxy.js" ] +} diff --git a/chromium/chrome/browser/resources/settings/chromeos/device_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/device_page/BUILD.gn index a9273bb0410..56c8f9e9eab 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/device_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/device_page/BUILD.gn @@ -82,10 +82,10 @@ js_library("display") { "//ui/webui/resources/js:i18n_behavior", "//ui/webui/resources/js/cr/ui:focus_without_ink", ] - externs_list = [ - "$externs_path/settings_private.js", - "$externs_path/system_display.js", - ] + externs_list = chrome_extension_public_externs + [ + "$externs_path/settings_private.js", + "$externs_path/system_display.js", + ] extra_sources = [ "$interfaces_path/system_display_interface.js" ] } diff --git a/chromium/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn index 7bd578dc434..2f90cb59d16 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn @@ -3,6 +3,9 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/polymer.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") +import("../os_settings.gni") js_type_check("closure_compile") { deps = [ ":localized_link" ] @@ -12,24 +15,20 @@ js_library("localized_link") { deps = [ "//ui/webui/resources/js:assert" ] } -# TODO: Uncomment as the Polymer3 migration makes progress. -#js_type_check("closure_compile_module") { -# is_polymer3 = true -# deps = [ -# ":localized_link.m" -# ] -#} +js_type_check("closure_compile_module") { + is_polymer3 = true + deps = [ ":localized_link.m" ] +} js_library("localized_link.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/localized_link/localized_link.m.js" ] deps = [ - # TODO: Fill those in. + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", ] extra_deps = [ ":localized_link_module" ] } -import("//tools/polymer/polymer.gni") - group("polymer3_elements") { public_deps = [ ":localized_link_module" ] } @@ -38,4 +37,8 @@ polymer_modulizer("localized_link") { js_file = "localized_link.js" html_file = "localized_link.html" html_type = "dom-module" + namespace_rewrites = os_settings_namespace_rewrites + auto_imports = + os_settings_auto_imports + + [ "ui/webui/resources/html/assert.html|assert,assertNotReached" ] } diff --git a/chromium/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn index 238c338b802..fb41281d966 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn @@ -63,6 +63,7 @@ js_library("multidevice_page") { "..:os_route", "../..:router", "../../controls:password_prompt_dialog", + "../../prefs:prefs_behavior", "../localized_link:localized_link", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:web_ui_listener_behavior", diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/BUILD.gn index 3c63e8b8004..a3971b9ff9b 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/BUILD.gn @@ -18,9 +18,13 @@ js_library("plugin_vm_browser_proxy") { js_library("plugin_vm_detail_view") { deps = [ + ":plugin_vm_browser_proxy", + ":plugin_vm_permission_dialog", "../:constants", + "../:permission_item", "../:store_client", "../:util", + "//ui/webui/resources/js:web_ui_listener_behavior", ] } @@ -31,6 +35,10 @@ js_library("plugin_vm_shared_paths") { ] } +js_library("plugin_vm_permission_dialog") { + deps = [ ":plugin_vm_browser_proxy" ] +} + # TODO: Uncomment as the Polymer3 migration makes progress. #js_type_check("closure_compile_module") { # is_polymer3 = true @@ -71,6 +79,7 @@ group("polymer3_elements") { public_deps = [ ":modulize", ":plugin_vm_detail_view_module", + ":plugin_vm_permission_dialog_module", ":plugin_vm_shared_paths_module", ] } @@ -81,6 +90,12 @@ polymer_modulizer("plugin_vm_detail_view") { html_type = "dom-module" } +polymer_modulizer("plugin_vm_permission_dialog") { + js_file = "plugin_vm_permission_dialog.js" + html_file = "plugin_vm_permission_dialog.html" + html_type = "dom-module" +} + polymer_modulizer("plugin_vm_shared_paths") { js_file = "plugin_vm_shared_paths.js" html_file = "plugin_vm_shared_paths.html" diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn index 1af53f2340e..6f55d8d266b 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn @@ -3,9 +3,13 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") +import("../os_settings.gni") js_type_check("closure_compile") { deps = [ + ":input_method_options_page", + ":input_method_util", ":manage_input_methods_page", ":os_add_languages_dialog", ":os_languages_page", @@ -16,6 +20,20 @@ js_type_check("closure_compile") { ] } +js_library("input_method_options_page") { + deps = [ + ":input_method_util", + "../..:router", + "../../languages_page:languages_types", + "../../prefs", + "//ui/webui/resources/js:i18n_behavior", + ] +} + +js_library("input_method_util") { + deps = [ "//ui/webui/resources/js:cr" ] +} + js_library("manage_input_methods_page") { deps = [ "../../languages_page:languages_types", @@ -26,6 +44,7 @@ js_library("manage_input_methods_page") { js_library("os_languages_section") { deps = [ + ":input_method_options_page", ":manage_input_methods_page", ":os_languages_page", "..:os_route", @@ -43,6 +62,7 @@ js_library("os_languages_section") { js_library("os_languages_page") { deps = [ + ":input_method_util", "..:metrics_recorder", "..:os_route", "../..:lifetime_browser_proxy", @@ -73,6 +93,8 @@ js_library("os_add_languages_dialog") { #js_type_check("closure_compile_module") { # is_polymer3 = true # deps = [ +# ":input_method_options_page.m", +# ":input_method_util.m", # ":manage_input_methods_page.m", # ":os_add_languages_dialog.m", # ":os_languages_page.m", @@ -80,6 +102,22 @@ js_library("os_add_languages_dialog") { # ] #} +js_library("input_method_util.m") { + sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.m.js" ] + deps = [ + # TODO: Fill those in. + ] + extra_deps = [ ":modulize" ] +} + +js_library("input_method_options_page.m") { + sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.m.js" ] + deps = [ + # TODO: Fill those in. + ] + extra_deps = [ ":input_method_options_page_module" ] +} + js_library("manage_input_methods_page.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_languages_page/manage_input_methods_page.m.js" ] deps = [ @@ -116,7 +154,9 @@ import("//tools/polymer/polymer.gni") group("polymer3_elements") { public_deps = [ + ":input_method_options_page_module", ":manage_input_methods_page_module", + ":modulize", ":os_add_languages_dialog_module", ":os_languages_page_module", ":os_languages_section_module", @@ -146,3 +186,14 @@ polymer_modulizer("os_languages_section") { html_file = "os_languages_section.html" html_type = "dom-module" } + +polymer_modulizer("input_method_options_page") { + js_file = "input_method_options_page.js" + html_file = "input_method_options_page.html" + html_type = "dom-module" +} + +js_modulizer("modulize") { + input_files = [ "input_method_util.js" ] + namespace_rewrites = os_settings_namespace_rewrites +} diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn index f89ff3750c3..32e7bbe7959 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn @@ -9,8 +9,10 @@ js_type_check("closure_compile") { } js_library("os_privacy_page") { - deps = - [ "//chrome/browser/resources/settings/controls:settings_toggle_button" ] + deps = [ + "//chrome/browser/resources/settings/controls:settings_toggle_button", + "//ui/webui/resources/js:load_time_data", + ] } # TODO: Uncomment as the Polymer3 migration makes progress. diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn index cf97405216f..e05a9896a07 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn @@ -3,6 +3,9 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/polymer.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") +import("../os_settings.gni") js_type_check("closure_compile") { deps = [ @@ -25,6 +28,7 @@ js_library("os_reset_page") { deps = [ "//ui/webui/resources/js:assert", "//ui/webui/resources/js:cr", + "//ui/webui/resources/js:load_time_data", "//ui/webui/resources/js/cr/ui:focus_without_ink", ] } @@ -34,20 +38,23 @@ js_library("os_reset_browser_proxy") { externs_list = [ "$externs_path/chrome_send.js" ] } -# TODO: Uncomment as the Polymer3 migration makes progress. -#js_type_check("closure_compile_module") { -# is_polymer3 = true -# deps = [ -# ":os_powerwash_dialog.m", -# ":os_reset_browser_proxy.m", -# ":os_reset_page.m" -# ] -#} +js_type_check("closure_compile_module") { + is_polymer3 = true + deps = [ + ":os_powerwash_dialog.m", + ":os_reset_browser_proxy.m", + ":os_reset_page.m", + ] +} js_library("os_powerwash_dialog.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.m.js" ] deps = [ - # TODO: Fill those in. + ":os_reset_browser_proxy.m", + "..:metrics_recorder.m", + "../..:lifetime_browser_proxy.m", + "../localized_link:localized_link.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] extra_deps = [ ":os_powerwash_dialog_module" ] } @@ -55,7 +62,8 @@ js_library("os_powerwash_dialog.m") { js_library("os_reset_browser_proxy.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_browser_proxy.m.js" ] deps = [ - # TODO: Fill those in. + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:cr.m", ] extra_deps = [ ":modulize" ] } @@ -63,13 +71,14 @@ js_library("os_reset_browser_proxy.m") { js_library("os_reset_page.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_page.m.js" ] deps = [ - # TODO: Fill those in. + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:load_time_data.m", + "//ui/webui/resources/js/cr/ui:focus_without_ink.m", ] extra_deps = [ ":os_reset_page_module" ] } -import("//tools/polymer/polymer.gni") - group("polymer3_elements") { public_deps = [ ":modulize", @@ -82,16 +91,21 @@ polymer_modulizer("os_powerwash_dialog") { js_file = "os_powerwash_dialog.js" html_file = "os_powerwash_dialog.html" html_type = "dom-module" + namespace_rewrites = os_settings_namespace_rewrites + auto_imports = os_settings_auto_imports } polymer_modulizer("os_reset_page") { js_file = "os_reset_page.js" html_file = "os_reset_page.html" html_type = "dom-module" + migrated_imports = settings_migrated_imports + namespace_rewrites = os_settings_namespace_rewrites + auto_imports = os_settings_auto_imports + + [ "ui/webui/resources/html/assert.html|assert" ] } -import("//ui/webui/resources/tools/js_modulizer.gni") - js_modulizer("modulize") { input_files = [ "os_reset_browser_proxy.js" ] + namespace_rewrites = os_settings_namespace_rewrites } diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_settings.gni b/chromium/chrome/browser/resources/settings/chromeos/os_settings.gni new file mode 100644 index 00000000000..400b8e0059e --- /dev/null +++ b/chromium/chrome/browser/resources/settings/chromeos/os_settings.gni @@ -0,0 +1,24 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") +import("../settings.gni") + +os_settings_namespace_rewrites = + settings_namespace_rewrites + [ + "settings.OsResetBrowserProxy|OsResetBrowserProxy", + "settings.recordSettingChange|recordSettingChange", + ] + +os_settings_auto_imports = settings_auto_imports + [ + "chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_browser_proxy.html|OsResetBrowserProxy,OsResetBrowserProxyImpl", + "chrome/browser/resources/settings/chromeos/metrics_recorder.html|recordSettingChange", + "chrome/browser/resources/settings/lifetime_browser_proxy.html|LifetimeBrowserProxy,LifetimeBrowserProxyImpl", + "chrome/browser/resources/settings/chromeos/os_route.html|routes", + "chrome/browser/resources/settings/route.html|routes", + "chrome/browser/resources/settings/router.html|Router,Route,RouteObserverBehavior", + "ui/webui/resources/html/polymer.html|Polymer,html,flush", + ] + +os_settings_migrated_imports = settings_migrated_imports diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn index f9e55626477..7afa56ffe1d 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn @@ -14,7 +14,6 @@ js_library("os_settings_page") { "..:os_route", "../..:router", "../..:search_settings", - "../../prefs:prefs_behavior", "../../settings_page:main_page_behavior", "../os_apps_page:android_apps_browser_proxy", "//ui/webui/resources/js:load_time_data", diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp b/chromium/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp index db555e9d3a1..c764effbb47 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp +++ b/chromium/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp @@ -1,13 +1,137 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> - <include name="IDR_OS_SETTINGS_SEARCH_HANDLER_M_JS" - file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/search_handler.m.js" + <include name="IDR_OS_SETTINGS_RESET_BROWSER_PROXY_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_browser_proxy.m.js" use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_RESET_POWERWASH_DIALOG_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_RESET_PAGE_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_page.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_BLUETOOTH_PAGE_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_page.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_BLUETOOTH_SUBPAGE_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_BLUETOOTH_DEVICE_LIST_ITEM_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_device_list_item.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_LOCALIZED_LINK_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/localized_link/localized_link.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_METRIC_RECORDER_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/metrics_recorder.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_OS_ICONS_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_icons.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_SETTINGS_OS_ROUTE_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_route.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_SETTINGS_OS_SETTINGS_ROUTE_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_settings_routes.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_SETTINGS_SUBPAGE_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/settings_page/settings_subpage.m.js" + use_base_dir="false" + compress="false" + type="BINDATA"/> + <include name="IDR_OS_SETTINGS_SETTINGS_ANIMATED_PAGES_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/settings_page/settings_animated_pages.m.js" + use_base_dir="false" + compress="false" + type="BINDATA"/> + <include name="IDR_OS_SETTINGS_SETTINGS_TOGGLE_BUTTON_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_toggle_button.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_SETTINGS_BOOLEAN_CONTROL_BEHAVIOR_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_boolean_control_behavior.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_PREF_CONTROL_BEHAVIOR_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/controls/pref_control_behavior.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_LIFETIME_BROWSER_PROXY_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/lifetime_browser_proxy.m.js" + use_base_dir="false" + compress="false" + preprocess="true" + type="BINDATA"/> + <include name="IDR_OS_SETTINGS_PREFS_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/prefs/prefs.m.js" + use_base_dir="false" + compress="false" + type="BINDATA"/> + <include name="IDR_OS_SETTINGS_PREFS_BEHAVIOR_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/prefs/prefs_behavior.m.js" + use_base_dir="false" + compress="false" + type="BINDATA"/> + <include name="IDR_OS_SETTINGS_PREFS_TYPES_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/prefs/prefs_types.m.js" + use_base_dir="false" + compress="false" + type="BINDATA"/> + <include name="IDR_OS_SETTINGS_NEARBY_SHARE_SUBPAGE_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/nearby_share_page/nearby_share_subpage.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_ROUTER_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/router.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_SETTINGS_SHARED_CSS_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/settings_shared_css.m.js" + use_base_dir="false" + preprocess="true" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_SETTINGS_VARS_CSS_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/settings_vars_css.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_I18N_SETUP_JS" + file="i18n_setup.js" + compress="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_SETTINGS_V3_HTML" file="chromeos/os_settings_v3.html" + compress="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_SETTINGS_V3_JS" file="chromeos/os_settings.js" + compress="false" type="BINDATA" /> -</grit-part>
\ No newline at end of file +</grit-part> diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_settings_search_box/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_settings_search_box/BUILD.gn index a206a3b623f..71f87b6c7d0 100644 --- a/chromium/chrome/browser/resources/settings/chromeos/os_settings_search_box/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/chromeos/os_settings_search_box/BUILD.gn @@ -22,6 +22,7 @@ js_library("os_settings_search_box") { "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar_search_field", "//ui/webui/resources/js:assert", ] + externs_list = [ "$externs_path/metrics_private.js" ] } js_library("os_search_result_row") { @@ -34,6 +35,7 @@ js_library("os_search_result_row") { "//ui/webui/resources/js:i18n_behavior", "//ui/webui/resources/js/cr/ui:focus_row_behavior", ] + externs_list = [ "$externs_path/metrics_private.js" ] } # TODO: Uncomment as the Polymer3 migration makes progress. @@ -51,6 +53,7 @@ js_library("os_search_result_row.m") { # TODO: Fill those in. ] extra_deps = [ ":os_search_result_row_module" ] + externs_list = [ "$externs_path/metrics_private.js" ] } js_library("os_settings_search_box.m") { @@ -59,6 +62,7 @@ js_library("os_settings_search_box.m") { # TODO: Fill those in. ] extra_deps = [ ":os_settings_search_box_module" ] + externs_list = [ "$externs_path/metrics_private.js" ] } import("//tools/polymer/polymer.gni") diff --git a/chromium/chrome/browser/resources/settings/controls/BUILD.gn b/chromium/chrome/browser/resources/settings/controls/BUILD.gn index 69216da31e1..506ca163505 100644 --- a/chromium/chrome/browser/resources/settings/controls/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/controls/BUILD.gn @@ -57,7 +57,8 @@ js_library("password_prompt_dialog") { "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog", "//ui/webui/resources/cr_elements/cr_input:cr_input", ] - externs_list = [ "$externs_path/quick_unlock_private.js" ] + externs_list = chrome_extension_public_externs + + [ "$externs_path/quick_unlock_private.js" ] extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ] } @@ -183,7 +184,8 @@ js_library("password_prompt_dialog.m") { "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", "//ui/webui/resources/cr_elements/cr_input:cr_input.m", ] - externs_list = [ "$externs_path/quick_unlock_private.js" ] + externs_list = chrome_extension_public_externs + + [ "$externs_path/quick_unlock_private.js" ] extra_deps = [ ":password_prompt_dialog_module" ] } diff --git a/chromium/chrome/browser/resources/settings/nearby_share_page/BUILD.gn b/chromium/chrome/browser/resources/settings/nearby_share_page/BUILD.gn new file mode 100644 index 00000000000..81c2a5030f6 --- /dev/null +++ b/chromium/chrome/browser/resources/settings/nearby_share_page/BUILD.gn @@ -0,0 +1,54 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/polymer.gni") +import("../settings.gni") + +js_type_check("closure_compile") { + deps = [ ":nearby_share_subpage" ] +} + +js_library("nearby_share_subpage") { + deps = [ + "../prefs", + "../prefs:prefs_behavior", + "../prefs:prefs_types", + "//ui/webui/resources/js:cr", + "//ui/webui/resources/js:i18n_behavior", + ] +} + +group("polymer3_elements") { + public_deps = [ + "../controls:polymer3_elements", + "../prefs:polymer3_elements", + ":nearby_share_subpage_module", + ] +} + +js_type_check("closure_compile_module") { + is_polymer3 = true + deps = [ ":nearby_share_subpage.m" ] +} + +js_library("nearby_share_subpage.m") { + sources = [ "$root_gen_dir/chrome/browser/resources/settings/nearby_share_page/nearby_share_subpage.m.js" ] + deps = [ + "../prefs:prefs.m", + "../prefs:prefs_behavior.m", + "../prefs:prefs_types.m", + "//ui/webui/resources/js:cr.m", + "//ui/webui/resources/js:i18n_behavior.m", + ] + extra_deps = [ ":nearby_share_subpage_module" ] +} + +polymer_modulizer("nearby_share_subpage") { + js_file = "nearby_share_subpage.js" + html_file = "nearby_share_subpage.html" + html_type = "dom-module" + namespace_rewrites = settings_namespace_rewrites + auto_imports = settings_auto_imports +} diff --git a/chromium/chrome/browser/resources/settings/os_settings_resources.grd b/chromium/chrome/browser/resources/settings/os_settings_resources.grd index cf80563c962..4e4138f4717 100644 --- a/chromium/chrome/browser/resources/settings/os_settings_resources.grd +++ b/chromium/chrome/browser/resources/settings/os_settings_resources.grd @@ -25,18 +25,10 @@ compress="false" type="BINDATA" /> <!-- App Management --> - <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_BITMAP_MOJO_LITE_JS" - file="${root_gen_dir}\skia\public\mojom\bitmap.mojom-lite.js" - use_base_dir="false" - compress="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_FILE_PATH_MOJO_LITE_JS" file="${root_gen_dir}\mojo\public\mojom\base\file_path.mojom-lite.js" use_base_dir="false" compress="false" type="BINDATA" /> - <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS" - file="${root_gen_dir}\skia\public\mojom\image_info.mojom-lite.js" - use_base_dir="false" - compress="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_MOJO_LITE_JS" file="${root_gen_dir}\ui\gfx\image\mojom\image.mojom-lite.js" use_base_dir="false" @@ -46,7 +38,7 @@ use_base_dir="false" compress="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_TYPES_MOJO_LITE_JS" - file="${root_gen_dir}\chrome\services\app_service\public\mojom\types.mojom-lite.js" + file="${root_gen_dir}\components\services\app_service\public\mojom\types.mojom-lite.js" use_base_dir="false" compress="false" type="BINDATA" /> @@ -77,18 +69,30 @@ <structure name="IDR_OS_SETTINGS_A11Y_PAGE_HTML" file="chromeos/os_a11y_page/os_a11y_page.html" compress="false" type="chrome_html" /> - <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_PAGE_JS" + <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_JS" file="chromeos/ambient_mode_page/ambient_mode_page.js" compress="false" type="chrome_html" /> - <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_PAGE_HTML" + <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_HTML" file="chromeos/ambient_mode_page/ambient_mode_page.html" compress="false" type="chrome_html" /> - <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_BROWSER_PROXY_JS" + <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PHOTOS_PAGE_JS" + file="chromeos/ambient_mode_page/ambient_mode_photos_page.js" + compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PHOTOS_PAGE_HTML" + file="chromeos/ambient_mode_page/ambient_mode_photos_page.html" + compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_BROWSER_PROXY_JS" file="chromeos/ambient_mode_page/ambient_mode_browser_proxy.js" compress="false" type="chrome_html" /> - <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_BROWSER_PROXY_HTML" + <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_BROWSER_PROXY_HTML" file="chromeos/ambient_mode_page/ambient_mode_browser_proxy.html" compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_AMBIENT_CONSTANTS_JS" + file="chromeos/ambient_mode_page/constants.js" + compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_AMBIENT_CONSTANTS_HTML" + file="chromeos/ambient_mode_page/constants.html" + compress="false" type="chrome_html" /> <structure name="IDR_OS_SETTINGS_APPS_PAGE_JS" file="chromeos/os_apps_page/os_apps_page.js" compress="false" type="chrome_html" /> @@ -248,6 +252,12 @@ <structure name="IDR_OS_SETTINGS_APP_MANAGEMENT_PLUGIN_VM_BROWSER_PROXY_HTML" file="chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_browser_proxy.html" compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_APP_MANAGEMENT_PLUGIN_VM_PERMISSION_DIALOG_JS" + file="chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_permission_dialog.js" + compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_APP_MANAGEMENT_PLUGIN_VM_PERMISSION_DIALOG_HTML" + file="chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_permission_dialog.html" + compress="false" type="chrome_html" /> <structure name="IDR_OS_SETTINGS_CAPTIONS_SUBPAGE_JS" file="a11y_page/captions_subpage.js" compress="false" type="chrome_html" /> @@ -349,6 +359,9 @@ file="lifetime_browser_proxy.js" compress="false" type="chrome_html" preprocess="true" /> + <structure name="IDR_OS_SETTINGS_SEARCH_SETTINGS_HTML" + file="search_settings.html" + compress="false" type="chrome_html" /> <structure name="IDR_OS_SETTINGS_SEARCH_SETTINGS_JS" file="search_settings.js" compress="false" type="chrome_html" /> @@ -375,7 +388,8 @@ compress="false" type="chrome_html" /> <structure name="IDR_OS_SETTINGS_CR_SETTINGS_SUBPAGE_JS" file="settings_page/settings_subpage.js" - compress="false" type="chrome_html" /> + compress="false" type="chrome_html" + preprocess="true" /> <structure name="IDR_OS_SETTINGS_CR_SETTINGS_PAGE_CSS_HTML" file="settings_page_css.html" compress="false" type="chrome_html" /> @@ -657,6 +671,18 @@ <structure name="IDR_OS_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_PAGE_JS" file="chromeos/os_languages_page/manage_input_methods_page.js" compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_LANGUAGES_INPUT_METHOD_OPTIONS_PAGE_HTML" + file="chromeos/os_languages_page/input_method_options_page.html" + compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_LANGUAGES_INPUT_METHOD_OPTIONS_PAGE_JS" + file="chromeos/os_languages_page/input_method_options_page.js" + compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_LANGUAGES_INPUT_METHOD_UTIL_HTML" + file="chromeos/os_languages_page/input_method_util.html" + compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_LANGUAGES_INPUT_METHOD_UTIL_JS" + file="chromeos/os_languages_page/input_method_util.js" + compress="false" type="chrome_html" /> <structure name="IDR_OS_SETTINGS_LANGUAGES_SMART_INPUTS_PAGE_HTML" file="chromeos/os_languages_page/smart_inputs_page.html" compress="false" type="chrome_html" /> @@ -1095,6 +1121,12 @@ <structure name="IDR_OS_SETTINGS_DATE_TIME_TYPES_JS" file="chromeos/date_time_page/date_time_types.js" compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_TIMEZONE_BROWSER_PROXY_JS" + file="chromeos/date_time_page/timezone_browser_proxy.js" + compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_TIMEZONE_BROWSER_PROXY_HTML" + file="chromeos/date_time_page/timezone_browser_proxy.html" + compress="false" type="chrome_html" /> <structure name="IDR_OS_SETTINGS_TIMEZONE_SELECTOR_HTML" file="chromeos/date_time_page/timezone_selector.html" compress="false" type="chrome_html" /> @@ -1206,6 +1238,12 @@ <structure name="IDR_OS_SETTINGS_MULTIDEVICE_TETHER_ITEM_JS" file="chromeos/multidevice_page/multidevice_tether_item.js" compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_SUBPAGE_HTML" + file="nearby_share_page/nearby_share_subpage.html" + compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_SUBPAGE_JS" + file="nearby_share_page/nearby_share_subpage.js" + compress="false" type="chrome_html" /> <structure name="IDR_OS_SETTINGS_NETWORK_PROXY_SECTION_HTML" file="chromeos/internet_page/network_proxy_section.html" compress="false" type="chrome_html" /> diff --git a/chromium/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd b/chromium/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd index 88da13ccd00..a6e99635d9f 100644 --- a/chromium/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd +++ b/chromium/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd @@ -17,27 +17,23 @@ use_base_dir="false" flattenhtml="true" allowexternalscript="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OS_SETTINGS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\settings\chromeos\crisper.js" use_base_dir="false" flattenhtml="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OS_SETTINGS_LAZY_LOAD_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\chromeos\lazy_load.vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OS_SETTINGS_LAZY_LOAD_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\settings\chromeos\lazy_load.crisper.js" use_base_dir="false" flattenhtml="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_OS_SETTINGS_MANIFEST" file="os_settings_manifest.json" type="BINDATA" @@ -54,53 +50,46 @@ type="BINDATA" /> <!-- App Management --> - <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_BITMAP_MOJO_LITE_JS" - file="${root_gen_dir}\skia\public\mojom\bitmap.mojom-lite.js" - compress="gzip" - use_base_dir="false" - type="BINDATA" /> <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_FILE_PATH_MOJO_LITE_JS" file="${root_gen_dir}\mojo\public\mojom\base\file_path.mojom-lite.js" - compress="gzip" - use_base_dir="false" - type="BINDATA" /> - <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS" - file="${root_gen_dir}\skia\public\mojom\image_info.mojom-lite.js" - compress="gzip" use_base_dir="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_MOJO_LITE_JS" file="${root_gen_dir}\ui\gfx\image\mojom\image.mojom-lite.js" - compress="gzip" use_base_dir="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\app_management\app_management.mojom-lite.js" - compress="gzip" use_base_dir="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_TYPES_MOJO_LITE_JS" - file="${root_gen_dir}\chrome\services\app_service\public\mojom\types.mojom-lite.js" - compress="gzip" + file="${root_gen_dir}\components\services\app_service\public\mojom\types.mojom-lite.js" use_base_dir="false" type="BINDATA" /> <!-- Search --> <include name="IDR_OS_SETTINGS_SEARCH_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\search.mojom-lite.js" - compress="gzip" use_base_dir="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_SEARCH_RESULT_ICON_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\search_result_icon.mojom-lite.js" - compress="gzip" use_base_dir="false" type="BINDATA" /> <include name="IDR_OS_SETTINGS_USER_ACTION_RECORDER_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\user_action_recorder.mojom-lite.js" - compress="gzip" use_base_dir="false" type="BINDATA" /> + + <!-- Polymer3 related files--> + <include name="IDR_OS_SETTINGS_SETTINGS_ROLLUP_JS" + file="${root_gen_dir}\chrome\browser\resources\settings\chromeos\os_settings.rollup.js" + use_base_dir="false" + preprocess="true" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_OS_SETTINGS_V3_HTML" + file="chromeos/os_settings_v3.html" + type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/settings/safety_check_page/BUILD.gn b/chromium/chrome/browser/resources/settings/safety_check_page/BUILD.gn index bbe3b9a0e4d..bf337dd7635 100644 --- a/chromium/chrome/browser/resources/settings/safety_check_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/safety_check_page/BUILD.gn @@ -12,11 +12,12 @@ js_type_check("closure_compile_module") { deps = [ ":safety_check_browser_proxy", ":safety_check_child", - ":safety_check_extensions_element", + ":safety_check_chrome_cleaner_child", + ":safety_check_extensions_child", ":safety_check_page", - ":safety_check_passwords_element", - ":safety_check_safe_browsing_element", - ":safety_check_updates_element", + ":safety_check_passwords_child", + ":safety_check_safe_browsing_child", + ":safety_check_updates_child", ] } @@ -32,7 +33,19 @@ js_library("safety_check_child") { ] } -js_library("safety_check_extensions_element") { +js_library("safety_check_chrome_cleaner_child") { + deps = [ + ":safety_check_child", + "..:metrics_browser_proxy", + "..:route", + "..:router.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:web_ui_listener_behavior.m", + ] +} + +js_library("safety_check_extensions_child") { deps = [ ":safety_check_child", "..:metrics_browser_proxy", @@ -46,10 +59,11 @@ js_library("safety_check_extensions_element") { js_library("safety_check_page") { deps = [ ":safety_check_browser_proxy", - ":safety_check_extensions_element", - ":safety_check_passwords_element", - ":safety_check_safe_browsing_element", - ":safety_check_updates_element", + ":safety_check_chrome_cleaner_child", + ":safety_check_extensions_child", + ":safety_check_passwords_child", + ":safety_check_safe_browsing_child", + ":safety_check_updates_child", "..:hats_browser_proxy", "..:metrics_browser_proxy", "../autofill_page:password_manager_proxy", @@ -62,7 +76,7 @@ js_library("safety_check_page") { ] } -js_library("safety_check_passwords_element") { +js_library("safety_check_passwords_child") { deps = [ ":safety_check_child", "..:metrics_browser_proxy", @@ -75,7 +89,7 @@ js_library("safety_check_passwords_element") { ] } -js_library("safety_check_safe_browsing_element") { +js_library("safety_check_safe_browsing_child") { deps = [ ":safety_check_child", "..:metrics_browser_proxy", @@ -88,7 +102,7 @@ js_library("safety_check_safe_browsing_element") { ] } -js_library("safety_check_updates_element") { +js_library("safety_check_updates_child") { deps = [ ":safety_check_child", "..:lifetime_browser_proxy.m", @@ -102,10 +116,11 @@ js_library("safety_check_updates_element") { html_to_js("web_components") { js_files = [ "safety_check_child.js", - "safety_check_extensions_element.js", + "safety_check_chrome_cleaner_child.js", + "safety_check_extensions_child.js", "safety_check_page.js", - "safety_check_passwords_element.js", - "safety_check_safe_browsing_element.js", - "safety_check_updates_element.js", + "safety_check_passwords_child.js", + "safety_check_safe_browsing_child.js", + "safety_check_updates_child.js", ] } diff --git a/chromium/chrome/browser/resources/settings/settings.gni b/chromium/chrome/browser/resources/settings/settings.gni index 48e79e57b99..0c82dda4fd4 100644 --- a/chromium/chrome/browser/resources/settings/settings.gni +++ b/chromium/chrome/browser/resources/settings/settings.gni @@ -14,7 +14,6 @@ settings_namespace_rewrites = [ "settings.AccountManagerBrowserProxy|AccountManagerBrowserProxy", "settings.Account|Account", "settings.ALL_SITES_DIALOG|ALL_SITES_DIALOG", - "settings.AllSitesAction|AllSitesAction", "settings.AllSitesAction2|AllSitesAction2", "settings.AndroidInfoBrowserProxy|AndroidInfoBrowserProxy", "settings.AndroidSmsInfo|AndroidSmsInfo", @@ -97,6 +96,7 @@ settings_namespace_rewrites = [ "settings.MetricsReporting|MetricsReporting", "settings.SafetyCheckBrowserProxy|SafetyCheckBrowserProxy", "settings.SafetyCheckCallbackConstants|SafetyCheckCallbackConstants", + "settings.SafetyCheckChromeCleanerStatus|SafetyCheckChromeCleanerStatus", "settings.SafetyCheckExtensionsStatus|SafetyCheckExtensionsStatus", "settings.SafetyCheckIconStatus|SafetyCheckIconStatus", "settings.SafetyCheckParentStatus|SafetyCheckParentStatus", diff --git a/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn b/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn index fda50ecb1e5..c7432bfa778 100644 --- a/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn +++ b/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn @@ -46,7 +46,9 @@ js_library("settings_subpage") { "//ui/webui/resources/cr_elements/cr_search_field:cr_search_field", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:find_shortcut_behavior", + "//ui/webui/resources/js:i18n_behavior", "//ui/webui/resources/js:load_time_data", + "//ui/webui/resources/js:util", "//ui/webui/resources/js/cr/ui:focus_without_ink", ] } @@ -102,7 +104,9 @@ js_library("settings_subpage.m") { "//ui/webui/resources/cr_elements/cr_search_field:cr_search_field.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:find_shortcut_behavior.m", + "//ui/webui/resources/js:i18n_behavior.m", "//ui/webui/resources/js:load_time_data.m", + "//ui/webui/resources/js:util.m", "//ui/webui/resources/js/cr/ui:focus_without_ink.m", ] extra_deps = [ ":settings_subpage_module" ] @@ -150,6 +154,7 @@ polymer_modulizer("settings_subpage") { "third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/iron-resizable-behavior.html|IronResizableBehavior", "ui/webui/resources/html/assert.html|assert", "ui/webui/resources/html/polymer.html|html, Polymer, afterNextRender", + "ui/webui/resources/html/util.html|listenOnce", ] namespace_rewrites = settings_namespace_rewrites + [ "Polymer.IronResizableBehavior|IronResizableBehavior" ] diff --git a/chromium/chrome/browser/resources/settings/settings_resources_v3.grdp b/chromium/chrome/browser/resources/settings/settings_resources_v3.grdp index 4953d88930c..72c22ccadf5 100644 --- a/chromium/chrome/browser/resources/settings/settings_resources_v3.grdp +++ b/chromium/chrome/browser/resources/settings/settings_resources_v3.grdp @@ -86,10 +86,23 @@ file="autofill_page/blocking_request_manager.js" compress="false" type="BINDATA" /> </if> - <include name="IDR_SETTINGS_AUTOFILL_PAGE_SHOW_PASSWORD_BEHAVIOR_JS" - file="autofill_page/show_password_behavior.js" + <include name="IDR_SETTINGS_AUTOFILL_PAGE_MERGE_EXCEPTIONS_STORE_COPIES_BEHAVIOR_JS" + file="autofill_page/merge_exceptions_store_copies_behavior.js" + compress="false" type="BINDATA" + preprocess="true" /> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_MERGE_PASSWORDS_STORE_COPIES_BEHAVIOR_JS" + file="autofill_page/merge_passwords_store_copies_behavior.js" compress="false" type="BINDATA" preprocess="true" /> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_MULTI_STORE_EXCEPTION_ENTRY_JS" + file="autofill_page/multi_store_exception_entry.js" + compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_MULTI_STORE_ID_HANDLER_JS" + file="autofill_page/multi_store_id_handler.js" + compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_MULTI_STORE_PASSWORD_UI_ENTRY_JS" + file="autofill_page/multi_store_password_ui_entry.js" + compress="false" type="BINDATA" /> <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_CHECK_JS" file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_check.js" use_base_dir="false" @@ -115,6 +128,11 @@ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_list_item.js" use_base_dir="false" compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORDS_LIST_HANDLER_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js" + use_base_dir="false" + compress="false" type="BINDATA" + preprocess="true"/> <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_MANAGER_PROXY_JS" file="autofill_page/password_manager_proxy.js" compress="false" type="BINDATA" /> @@ -127,11 +145,26 @@ use_base_dir="false" compress="false" type="BINDATA" preprocess="true" /> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORDS_DEVICE_SECTION_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/passwords_device_section.js" + use_base_dir="false" + compress="false" type="BINDATA" + preprocess="true" /> <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_EDIT_DIALOG_JS" file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js" use_base_dir="false" compress="false" type="BINDATA" preprocess="true" /> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_MOVE_TO_ACCOUNT_DIALOG_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.js" + use_base_dir="false" + compress="false" type="BINDATA" + preprocess="true" /> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_REMOVE_DIALOG_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_remove_dialog.js" + use_base_dir="false" + compress="false" type="BINDATA" + preprocess="true" /> <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORDS_EXPORT_DIALOG_JS" file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.js" use_base_dir="false" @@ -141,6 +174,10 @@ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/payments_section.js" use_base_dir="false" compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_AUTOFILL_PAGE_SHOW_PASSWORD_BEHAVIOR_JS" + file="autofill_page/show_password_behavior.js" + compress="false" type="BINDATA" + preprocess="true" /> <include name="IDR_SETTINGS_BASIC_PAGE_BASIC_PAGE_JS" file="${root_gen_dir}/chrome/browser/resources/settings/basic_page/basic_page.js" use_base_dir="false" @@ -412,9 +449,6 @@ use_base_dir="false" preprocess="true" compress="false" type="BINDATA" /> - <include name="IDR_SETTINGS_PLURAL_STRING_PROXY_JS" - file="plural_string_proxy.js" - compress="false" type="BINDATA" /> <include name="IDR_SETTINGS_PREFS_PREFS_M_JS" file="${root_gen_dir}/chrome/browser/resources/settings/prefs/prefs.m.js" use_base_dir="false" @@ -551,24 +585,28 @@ file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_child.js" use_base_dir="false" compress="false" type="BINDATA" /> - <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_EXTENSIONS_ELEMENT_JS" - file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_element.js" + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_CHROME_CLEANER_CHILD_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_chrome_cleaner_child.js" + use_base_dir="false" + compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_EXTENSIONS_CHILD_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_child.js" use_base_dir="false" compress="false" type="BINDATA" /> <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_PAGE_JS" file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_page.js" use_base_dir="false" compress="false" type="BINDATA" /> - <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_PASSWORDS_ELEMENT_JS" - file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_element.js" + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_PASSWORDS_CHILD_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_child.js" use_base_dir="false" compress="false" type="BINDATA" /> - <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_SAFE_BROWSING_ELEMENT_JS" - file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_element.js" + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_SAFE_BROWSING_CHILD_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_child.js" use_base_dir="false" compress="false" type="BINDATA" /> - <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_UPDATES_ELEMENT_JS" - file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_updates_element.js" + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_UPDATES_CHILD_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_updates_child.js" use_base_dir="false" compress="false" type="BINDATA" /> <include name="IDR_SETTINGS_SEARCH_ENGINES_BROWSER_PROXY_M_JS" @@ -627,7 +665,8 @@ <include name="IDR_SETTINGS_SETTINGS_PAGE_SETTINGS_SUBPAGE_M_JS" file="${root_gen_dir}/chrome/browser/resources/settings/settings_page/settings_subpage.m.js" use_base_dir="false" - compress="false" type="BINDATA" /> + compress="false" type="BINDATA" + preprocess="true" /> <include name="IDR_SETTINGS_SETTINGS_UI_SETTINGS_UI_JS" file="${root_gen_dir}/chrome/browser/resources/settings/settings_ui/settings_ui.js" use_base_dir="false" diff --git a/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd b/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd index 51e23355bdf..aa1881dbc5d 100644 --- a/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd +++ b/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd @@ -14,74 +14,58 @@ <includes> <include name="IDR_SETTINGS_IMAGES_COOKIES_BANNER_SVG" file="images/cookies_banner.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_COOKIES_BANNER_DARK_SVG" file="images/cookies_banner_dark.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_PERMISSIONS_BANNER_SVG" file="images/permissions_banner.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_PERMISSIONS_BANNER_DARK_SVG" file="images/permissions_banner_dark.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_SAFE_BROWSING_BANNER_SVG" file="images/safe_browsing_banner.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_SAFE_BROWSING_BANNER_DARK_SVG" file="images/safe_browsing_banner_dark.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_SYNC_BANNER_SVG" file="images/sync_banner.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_SYNC_BANNER_DARK_SVG" file="images/sync_banner_dark.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_NEUTRAL_SVG" file="images/password_check_neutral.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_NEUTRAL_DARK_SVG" file="images/password_check_neutral_dark.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_POSITIVE_SVG" file="images/password_check_positive.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_POSITIVE_DARK_SVG" file="images/password_check_positive_dark.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <!-- Polymer 3 related files --> <include name="IDR_SETTINGS_SETTINGS_V3_HTML" file="settings_v3.html" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_SETTINGS_SETTINGS_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\settings\settings.rollup.js" use_base_dir="false" preprocess="true" - compress="gzip" type="BINDATA" /> <include name="IDR_SETTINGS_LAZY_LOAD_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.rollup.js" preprocess="true" type="BINDATA" - compress="gzip" use_base_dir="false" /> <include name="IDR_SETTINGS_SHARED_ROLLUP_JS" file="${root_gen_dir}\chrome\browser\resources\settings\shared.rollup.js" preprocess="true" type="BINDATA" - compress="gzip" use_base_dir="false" /> </includes> </release> diff --git a/chromium/chrome/browser/resources/signin/BUILD.gn b/chromium/chrome/browser/resources/signin/BUILD.gn index 8f8022c8193..f3e1f7e8491 100644 --- a/chromium/chrome/browser/resources/signin/BUILD.gn +++ b/chromium/chrome/browser/resources/signin/BUILD.gn @@ -8,8 +8,10 @@ group("closure_compile") { deps = [ "sync_confirmation:closure_compile" ] if (!is_chromeos) { deps += [ + "profile_picker:closure_compile", "signin_email_confirmation:closure_compile", "signin_error:closure_compile", + "signin_reauth:closure_compile", ] } } @@ -23,6 +25,7 @@ group("web_components") { public_deps += [ "signin_email_confirmation:web_components", "signin_error:web_components", + "signin_reauth:web_components", ] } } diff --git a/chromium/chrome/browser/resources/signin/profile_picker/BUILD.gn b/chromium/chrome/browser/resources/signin/profile_picker/BUILD.gn new file mode 100644 index 00000000000..e27205ad0b0 --- /dev/null +++ b/chromium/chrome/browser/resources/signin/profile_picker/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ + ":profile_picker_app", + ":profile_picker_main_view", + ] +} + +js_library("profile_picker_main_view") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/iron-icon", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m", + ] +} + +js_library("profile_picker_app") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager.m", + ] +} + +html_to_js("web_components") { + js_files = [ + "profile_picker_app.js", + "profile_picker_main_view.js", + ] +} diff --git a/chromium/chrome/browser/resources/signin/profile_picker/icons.js b/chromium/chrome/browser/resources/signin/profile_picker/icons.js new file mode 100644 index 00000000000..81d509c0c86 --- /dev/null +++ b/chromium/chrome/browser/resources/signin/profile_picker/icons.js @@ -0,0 +1,15 @@ +import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js'; + +const element = document.createElement('iron-iconset-svg'); +element.name = 'profiles'; +element.size = 74; +element.innerHTML = ` +<svg> + <defs> + <g id="add" viewBox="0 0 74 74"> + <circle cx="37" cy="37" r="37" stroke="none"/> + <path d="M36.9999 46.4349C36.1315 46.4349 35.4274 45.7309 35.4274 44.8624V38.5724H29.1374C28.269 38.5724 27.5649 37.8684 27.5649 36.9999C27.5649 36.1315 28.269 35.4274 29.1374 35.4274H35.4274V29.1374C35.4274 28.269 36.1315 27.5649 36.9999 27.5649C37.8684 27.5649 38.5724 28.269 38.5724 29.1374V35.4274H44.8624C45.7309 35.4274 46.4349 36.1315 46.4349 36.9999C46.4349 37.8684 45.7309 38.5724 44.8624 38.5724H38.5724V44.8624C38.5724 45.7309 37.8684 46.4349 36.9999 46.4349Z" fill="var(--iron-icon-stroke-color)"/> + </g> + </defs> +</svg>`; +document.head.appendChild(element); diff --git a/chromium/chrome/browser/resources/signin/profile_picker/profile_picker.html b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker.html index 8ddf6a371f0..ce6fe52046e 100644 --- a/chromium/chrome/browser/resources/signin/profile_picker/profile_picker.html +++ b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker.html @@ -2,7 +2,18 @@ <html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> + <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> </head> <body> + <style> + @media (prefers-color-scheme: dark) { + html { + background: var(--md-background-color); + } + } + </style> + <profile-picker-app></profile-picker-app> + <script type="module" src="profile_picker_app.js"></script> </body> </html> diff --git a/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_app.html b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_app.html new file mode 100644 index 00000000000..e227ef80fef --- /dev/null +++ b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_app.html @@ -0,0 +1,12 @@ +<style> + cr-view-manager { + display: flex; + font-size: 100%; + margin: 0; + min-height: 100vh; + } +</style> +<cr-view-manager> + <profile-picker-main-view slot="view" class="active"> + </profile-picker-main-view> +</cr-view-manager> diff --git a/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_app.js b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_app.js new file mode 100644 index 00000000000..83e6c76fbd6 --- /dev/null +++ b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_app.js @@ -0,0 +1,14 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.m.js'; +import './profile_picker_main_view.js'; + +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +Polymer({ + is: 'profile-picker-app', + + _template: html`{__html_template__}`, +}); diff --git a/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.html b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.html new file mode 100644 index 00000000000..5700543c6d2 --- /dev/null +++ b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.html @@ -0,0 +1,54 @@ +<style> + .profiles-container { + --grid-gutter: 12px; + --max-columns: 4; + --profile-item-height:178px; + --profile-item-width: 162px; + align-items: center; + display: grid; + height: 80%; + grid-column-gap: var(--grid-gutter); + grid-row-gap: var(--grid-gutter); + grid-template-columns: repeat(auto-fit, var(--profile-item-width)); + justify-content: center; + margin: auto; + max-width: calc(var(--profile-item-width) * var(--max-columns) + + var(--grid-gutter) * var(--max-columns)); + } + +.profile-item { + align-items: center; + display: flex; + flex-direction: column; + height: var(--profile-item-height); + justify-content: center; + width: var(--profile-item-width); + } + + #addProfile { + border: 1px dashed; + border-color: var(--google-grey-400); + border-radius: 12px; + } + + cr-icon-button[iron-icon='profiles:add'] { + --cr-icon-button-icon-size: 74px; + --cr-icon-button-size: 84px; + --cr-icon-button-fill-color: var(--google-grey-refresh-100); + --cr-icon-button-margin-end: 0px; + --cr-icon-button-margin-start: 0px; + --cr-icon-button-stroke-color: var(--google-grey-refresh-700); + } + +@media (prefers-color-scheme: dark) { + /* TODO(msalama): Dark mode mocks not ready yet.*/ +} +</style> +<div class="profiles-container"> + <div id="addProfile" class="profile-item"> + <!-- TODO(msalama): Add title, aria-label once strings are ready--> + <cr-icon-button iron-icon="profiles:add" + on-click="onAddProfileClick_"> + </cr-icon-button> + </div> +</div> diff --git a/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js new file mode 100644 index 00000000000..bde47adde55 --- /dev/null +++ b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js @@ -0,0 +1,20 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; +import 'chrome://resources/cr_elements/shared_vars_css.m.js'; +import './icons.js'; + +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +Polymer({ + is: 'profile-picker-main-view', + + _template: html`{__html_template__}`, + + /** @private */ + onAddProfileClick_() { + // TODO(msalama): do something. + }, +}); diff --git a/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd index d77a8a27541..244cc063482 100644 --- a/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd +++ b/chromium/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd @@ -11,12 +11,26 @@ <output filename="profile_picker_resources.pak" type="data_package" /> </outputs> <release seq="1"> + <includes> + <!-- Generated Polymer 3 elements --> + <include name="IDR_PROFILE_PICKER_PROFILE_PICKER_MAIN_VIEW_JS" + file="${root_gen_dir}/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js" + use_base_dir="false" type="BINDATA" preprocess="true"/> + <include name="IDR_PROFILE_PICKER_PROFILE_PICKER_APP_JS" + file="${root_gen_dir}/chrome/browser/resources/signin/profile_picker/profile_picker_app.js" + use_base_dir="false" type="BINDATA" preprocess="true"/> + </includes> <structures> <structure name="IDR_PROFILE_PICKER_PROFILE_PICKER_HTML" file="profile_picker.html" type="chrome_html" compress="false"/> + <structure + name="IDR_PROFILE_PICKER_ICONS_JS" + file="icons.js" + type="chrome_html" + compress="false"/> </structures> </release> </grit> diff --git a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.html b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.html index b5d7e465d99..7e5090fa00e 100644 --- a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.html +++ b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.html @@ -37,17 +37,6 @@ color: var(--cr-primary-text-color); } } - - #closeButton { - margin-inline-start: 8px; - } - -<if expr="is_macosx or is_linux"> - #closeButton { - margin-inline-end: 8px; - margin-inline-start: 0; - } -</if> </style> <div class="container"> <div class="top-title-bar" id='dialogTitle'> @@ -75,7 +64,7 @@ </div> <div class="action-container"> <cr-button class="action-button" id="confirmButton" - on-click="onConfirm_"> + on-click="onConfirm_" autofocus> $i18n{signinEmailConfirmationConfirmLabel} </cr-button> <cr-button id="closeButton" on-click="onCancel_"> diff --git a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.js b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.js index f9756526a7f..5e3408f9426 100644 --- a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.js +++ b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.js @@ -10,7 +10,6 @@ import './signin_shared_css.js'; import './strings.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; Polymer({ @@ -30,19 +29,6 @@ Polymer({ 'signinEmailConfirmationCreateProfileButtonSubtitle', newEmail); this.$.startSyncRadioButtonSubtitle.textContent = loadTimeData.getStringF( 'signinEmailConfirmationStartSyncButtonSubtitle', newEmail); - - document.addEventListener('keydown', this.onKeyDown_.bind(this)); - }, - - onKeyDown_(e) { - // If the currently focused element isn't something that performs an action - // on "enter" being pressed and the user hits "enter", perform the default - // action of the dialog, which is "OK". - if (e.key == 'Enter' && - !/^(A|CR-BUTTON)$/.test(getDeepActiveElement().tagName)) { - this.$.confirmButton.click(); - e.preventDefault(); - } }, /** @private */ diff --git a/chromium/chrome/browser/resources/signin/signin_error/signin_error.js b/chromium/chrome/browser/resources/signin/signin_error/signin_error.js index fd8fd98f9e4..779b871ae88 100644 --- a/chromium/chrome/browser/resources/signin/signin_error/signin_error.js +++ b/chromium/chrome/browser/resources/signin/signin_error/signin_error.js @@ -2,19 +2,11 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; - function initialize() { - addWebUIListener('clear-focus', clearFocus); - // Prefer using |document.body.offsetHeight| instead of // |document.body.scrollHeight| as it returns the correct height of the // even when the page zoom in Chrome is different than 100%. chrome.send('initializedWithSize', [document.body.offsetHeight]); } -function clearFocus() { - document.activeElement.blur(); -} - document.addEventListener('DOMContentLoaded', initialize); diff --git a/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.html b/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.html index 8e5db6f273d..9b32f228187 100644 --- a/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.html +++ b/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.html @@ -10,10 +10,6 @@ margin-bottom: 0; } - #closeButton { - margin-inline-start: 8px; - } - #profile-blocking-error-message { margin-top: 30px; } @@ -31,13 +27,6 @@ margin-inline-end: 16px; width: var(--cr-icon-size); } - -<if expr="is_macosx or is_linux"> - #closeButton { - margin-inline-end: 8px; - margin-inline-start: 0; - } -</if> </style> <div class="container"> <div class="top-title-bar">$i18n{signinErrorTitle}</div> @@ -70,9 +59,8 @@ on-click="onSwitchToExistingProfile_"> $i18n{signinErrorSwitchLabel} </cr-button> - <cr-button id="closeButton" - hidden="[[switchButtonUnavailable_]]" - on-click="onConfirm_"> + <cr-button id="closeButton" hidden="[[switchButtonUnavailable_]]" + on-click="onConfirm_" autofocus> $i18n{signinErrorCloseLabel} </cr-button> <cr-button id="confirmButton" hidden="[[!switchButtonUnavailable_]]" diff --git a/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.js b/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.js index 5ed8b298b33..592338a6c56 100644 --- a/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.js +++ b/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.js @@ -65,25 +65,15 @@ Polymer({ }, }, - /** @private {?function(!Event)} */ - boundKeyDownHandler_: null, - /** @override */ attached() { - this.boundKeyDownHandler_ = this.onKeyDown_.bind(this); - document.addEventListener('keydown', this.boundKeyDownHandler_); - this.addWebUIListener('switch-button-unavailable', () => { this.switchButtonUnavailable_ = true; + // Move focus to the only displayed button in this case. + this.$$('#confirmButton').focus(); }); }, - /** @override */ - detached() { - document.removeEventListener('keydown', this.boundKeyDownHandler_); - this.boundKeyDownHandler_ = null; - }, - /** @private */ onConfirm_() { chrome.send('confirm'); @@ -98,16 +88,4 @@ Polymer({ onLearnMore_() { chrome.send('learnMore'); }, - - /** - * @param {!Event} e - * @private - */ - onKeyDown_(e) { - if (e.key == 'Enter' && - !/^(A|CR-BUTTON)$/.test(e.composedPath()[0].tagName)) { - this.onConfirm_(); - e.preventDefault(); - } - }, }); diff --git a/chromium/chrome/browser/resources/signin/signin_reauth/BUILD.gn b/chromium/chrome/browser/resources/signin/signin_reauth/BUILD.gn new file mode 100644 index 00000000000..5b8112b7bec --- /dev/null +++ b/chromium/chrome/browser/resources/signin/signin_reauth/BUILD.gn @@ -0,0 +1,33 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ + ":signin_reauth_app", + ":signin_reauth_browser_proxy", + ] +} + +js_library("signin_reauth_app") { + deps = [ + ":signin_reauth_browser_proxy", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:i18n_behavior.m", + "//ui/webui/resources/js:load_time_data.m", + "//ui/webui/resources/js:web_ui_listener_behavior.m", + ] +} + +js_library("signin_reauth_browser_proxy") { + deps = [ "//ui/webui/resources/js:cr.m" ] + externs_list = [ "$externs_path/chrome_send.js" ] +} + +html_to_js("web_components") { + js_files = [ "signin_reauth_app.js" ] +} diff --git a/chromium/chrome/browser/resources/signin/signin_reauth/images/account_passwords_reauth_illustration.svg b/chromium/chrome/browser/resources/signin/signin_reauth/images/account_passwords_reauth_illustration.svg new file mode 100644 index 00000000000..ec0caee138d --- /dev/null +++ b/chromium/chrome/browser/resources/signin/signin_reauth/images/account_passwords_reauth_illustration.svg @@ -0,0 +1 @@ +<svg width="540" height="170" viewBox="0 0 540 170" fill="none" xmlns="http://www.w3.org/2000/svg"><path opacity=".04" d="M281.956 123.563c14.58 0 26.399-.944 26.399-2.108 0-1.164-11.819-2.108-26.399-2.108s-26.399.944-26.399 2.108c0 1.164 11.819 2.108 26.399 2.108zm-136.22 4.217c14.58 0 26.399-.944 26.399-2.109 0-1.164-11.819-2.108-26.399-2.108s-26.399.944-26.399 2.108c0 1.165 11.819 2.109 26.399 2.109zm144.668 13.171v4.749h45.406v-9.487l-45.406 4.738z" fill="#202124"/><path d="M278.788 116.184V54.572c0-2.65 2.123-4.797 4.741-4.797h6.875v66.409h-11.616z" fill="#F8F9FA"/><path fill-rule="evenodd" clip-rule="evenodd" d="M283.512 48.721h7.948v68.518h-13.728V54.493a5.776 5.776 0 0 1 5.78-5.772zm6.021 66.594v-64.67h-6.021a3.85 3.85 0 0 0-3.853 3.848v60.822h9.874z" fill="#E8EAED"/><path d="M284.068 116.184V54.572a4.792 4.792 0 0 1 4.788-4.797h74.901a4.792 4.792 0 0 1 4.788 4.797v61.612h-84.477z" fill="#fff"/><path fill-rule="evenodd" clip-rule="evenodd" d="M288.771 48.721h75.072c3.18 0 5.758 2.584 5.758 5.772v62.746h-86.589V54.493c0-3.188 2.578-5.772 5.759-5.772zm78.911 5.772a3.843 3.843 0 0 0-3.839-3.848H288.77a3.843 3.843 0 0 0-3.839 3.848v60.822h82.751V54.493z" fill="#E8EAED"/><path d="M283.549 123.563c-2.63 0-4.761-2.205-4.761-4.926v-2.453h59.134v7.379h-54.373z" fill="#F8F9FA"/><path fill-rule="evenodd" clip-rule="evenodd" d="M277.732 115.13h61.246v9.487h-55.514c-3.166 0-5.732-2.685-5.732-5.998v-3.489zm59.336 7.488v-5.488h-57.425v1.489c0 2.209 1.711 3.999 3.821 3.999h53.604z" fill="#E8EAED"/><path d="M336.363 123.563c-2.638 0-4.777-2.205-4.777-4.926v-2.453h86.59v2.453c0 2.721-2.139 4.926-4.777 4.926h-77.036z" fill="#fff"/><path fill-rule="evenodd" clip-rule="evenodd" d="M330.53 115.13h88.702v3.489c0 3.313-2.574 5.998-5.748 5.998h-77.206c-3.174 0-5.748-2.685-5.748-5.998v-3.489zm86.786 3.489v-1.489h-84.87v1.489c0 2.209 1.716 3.999 3.832 3.999h77.206c2.116 0 3.832-1.79 3.832-3.999z" fill="#E8EAED"/><path d="M382.925 119.347h-16.088c-.949 0-1.859-.343-2.529-.952-.67-.61-1.045-1.436-1.043-2.297v-.968h23.232v.95c.007.864-.366 1.695-1.036 2.308-.671.614-1.584.959-2.536.959z" fill="#E8EAED"/><path fill="#F8F9FA" d="M290.404 57.154h70.75v52.706h-70.75z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M289.348 56.1h72.861v54.814h-72.861V56.1zm70.944 52.89V58.023h-69.027v50.967h69.027z" fill="#E8EAED"/><rect x="326.307" y="81.399" width="17.951" height="1.054" rx=".527" fill="#DADCE0"/><rect x="326.307" y="83.507" width="14.784" height="1.054" rx=".527" fill="#DADCE0"/><rect x="160.52" y="48.721" width="55.966" height="78.004" rx="5" fill="#fff"/><path fill-rule="evenodd" clip-rule="evenodd" d="M165.166 47.667h45.618c3.149 0 5.702 2.562 5.702 5.723v68.667c0 3.161-2.553 5.723-5.702 5.723h-45.618c-3.149 0-5.702-2.562-5.702-5.723V53.39c0-3.16 2.553-5.723 5.702-5.723zm49.419 5.722a3.808 3.808 0 0 0-3.801-3.815h-45.618a3.808 3.808 0 0 0-3.802 3.815v68.668a3.808 3.808 0 0 0 3.802 3.815h45.618a3.808 3.808 0 0 0 3.801-3.815V53.389z" fill="#E8EAED"/><path fill="#F8F9FA" d="M165.8 53.992h44.351v67.463H165.8z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M164.744 53.992h46.462v68.517h-46.462V53.992zm44.526 66.614V55.895h-42.59v64.711h42.59z" fill="#E8EAED"/><rect x="137.289" y="67.695" width="32.735" height="59.03" rx="5" fill="#fff"/><path fill-rule="evenodd" clip-rule="evenodd" d="M142.04 66.641h23.231c3.208 0 5.808 2.566 5.808 5.732v49.675c0 3.165-2.6 5.732-5.808 5.732H142.04c-3.207 0-5.808-2.567-5.808-5.732V72.373c0-3.166 2.601-5.732 5.808-5.732zm27.103 5.732c0-2.11-1.733-3.821-3.871-3.821H142.04c-2.138 0-3.872 1.71-3.872 3.821v49.675c0 2.11 1.734 3.821 3.872 3.821h23.232c2.138 0 3.871-1.711 3.871-3.821V72.373z" fill="#E8EAED"/><path fill="#E8EAED" d="M136.232 76.128h34.847v2.108h-34.847zm0 42.165h34.847v2.108h-34.847z"/><path fill="#F8F9FA" d="M138.344 78.237h30.623v40.056h-30.623z"/><rect x="145.736" y="71.912" width="15.839" height="2.108" rx="1" fill="#E8EAED"/><rect x="147.848" y="100.373" width="12.672" height="1.054" rx=".527" fill="#DADCE0"/><rect x="148.904" y="103.535" width="10.56" height="1.054" rx=".527" fill="#DADCE0"/><rect x="181.639" y="83.507" width="12.672" height="1.054" rx=".527" fill="#DADCE0"/><rect x="182.695" y="86.669" width="10.56" height="1.054" rx=".527" fill="#DADCE0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M148.292 88.135a5.809 5.809 0 0 1 5.374-3.574 5.793 5.793 0 0 1 5.798 5.787 5.798 5.798 0 0 1-3.581 5.365 5.816 5.816 0 0 1-6.334-1.255 5.791 5.791 0 0 1-1.257-6.323zm5.374-1.838a1.735 1.735 0 1 1 1.23 2.964 1.743 1.743 0 0 1-1.896.377 1.736 1.736 0 0 1 .666-3.34zm0 8.222c-1.4.001-2.707-.7-3.479-1.866 0-1.147 2.319-1.776 3.479-1.776 1.16 0 3.469.629 3.479 1.776a4.17 4.17 0 0 1-3.479 1.866zm29.483-26.434a5.807 5.807 0 0 1 5.393-3.552 5.803 5.803 0 0 1 5.769 5.798 5.798 5.798 0 0 1-3.595 5.36 5.815 5.815 0 0 1-6.334-1.275 5.788 5.788 0 0 1-1.233-6.331zm5.393-1.81a1.741 1.741 0 1 1 1.231 2.978 1.747 1.747 0 0 1-2.976-1.245 1.734 1.734 0 0 1 1.745-1.732zm0 8.229a4.162 4.162 0 0 1-3.48-1.87c0-1.152 2.317-1.782 3.48-1.782 1.164 0 3.471.63 3.481 1.782a4.153 4.153 0 0 1-3.481 1.87z" fill="#DADCE0"/><path d="M129.626 40.703c-4.229 1.222-7.12 4.922-7.121 9.115 0 .559.477 1.011 1.065 1.011.589 0 1.066-.452 1.066-1.01.001-3.304 2.278-6.22 5.611-7.182 3.333-.963 6.938.252 8.881 2.994l.441.622.755-.22a4.453 4.453 0 0 1 1.222-.175 4.29 4.29 0 0 1 2.948 1.16 3.86 3.86 0 0 1 1.223 2.8c0 .559.477 1.011 1.066 1.011.588 0 1.065-.452 1.065-1.01 0-1.587-.665-3.109-1.847-4.23-1.183-1.123-2.788-1.753-4.46-1.753a6.74 6.74 0 0 0-1.085.093c-2.545-3.072-6.841-4.379-10.83-3.226z" fill="#E8EAED"/><path d="M141.604 43.45a5.845 5.845 0 0 0-4.034 1.596.888.888 0 0 0 .002 1.299.998.998 0 0 0 1.363-.002 3.868 3.868 0 0 1 2.669-1.055c.533 0 .964-.412.964-.919 0-.507-.431-.919-.964-.918zm44.229-17.528c-1.67-.002-3.277.627-4.461 1.748-1.184 1.122-1.848 2.645-1.845 4.231.001.558.479 1.01 1.068 1.009.588-.002 1.064-.454 1.063-1.012a3.843 3.843 0 0 1 1.221-2.8 4.286 4.286 0 0 1 2.954-1.156 4.5 4.5 0 0 1 1.225.169l.751.213.438-.617c1.945-2.741 5.552-3.955 8.885-2.99 3.334.963 5.61 3.88 5.607 7.182 0 .558.477 1.01 1.065 1.01.589.001 1.066-.45 1.066-1.009.004-4.191-2.885-7.892-7.116-9.116-3.991-1.154-8.292.152-10.837 3.225a6.727 6.727 0 0 0-1.084-.087z" fill="#E8EAED"/><path d="M185.774 28.422a3.816 3.816 0 0 1 2.67 1.053.991.991 0 0 0 1.358.006.89.89 0 0 0 .006-1.299 5.78 5.78 0 0 0-4.046-1.597c-.531.003-.958.417-.955.924.004.508.437.916.967.913zm210.924 30.427c-3.482 0-6.306 2.676-6.306 5.977 0 .558.477 1.01 1.066 1.01.588 0 1.065-.452 1.065-1.01 0-2.185 1.87-3.957 4.177-3.957a4.5 4.5 0 0 1 1.223.168l.751.213.438-.617c1.944-2.74 5.552-3.955 8.885-2.99 3.334.964 5.61 3.88 5.607 7.182 0 .558.477 1.01 1.065 1.011.588 0 1.066-.451 1.066-1.01.004-4.19-2.885-7.891-7.116-9.115-3.991-1.155-8.292.151-10.837 3.224a6.727 6.727 0 0 0-1.084-.086z" fill="#E8EAED"/><path d="M396.639 60.294a3.854 3.854 0 0 1 2.652 1.053c.377.36.991.364 1.372.007a.883.883 0 0 0 .008-1.299c-1.063-1.018-2.512-1.593-4.026-1.598-.536-.001-.972.409-.973.916-.002.507.431.92.967.921z" fill="#E8EAED"/><rect x="317.178" y="74.461" width="103.485" height="30.569" rx="5.37" fill="#1A73E8"/><rect x="403.768" y="79.731" width="2.112" height="18.974" rx="1" fill="#EA4335"/><path fill="#fff" d="M328.794 88.164h15.839v2.108h-15.839z"/><path d="M333.784 82.454l7.668 13.254-2.075 1.195-7.668-13.253 2.075-1.196z" fill="#fff"/><path d="M341.452 83.65l-7.668 13.253-2.076-1.195 7.669-13.254 2.075 1.195zm11.629 4.514h15.839v2.108h-15.839z" fill="#fff"/><path d="M358.706 82.45l7.668 13.254-2.075 1.196-7.668-13.254 2.075-1.195z" fill="#fff"/><path d="M366.374 83.646L358.706 96.9l-2.075-1.196 7.668-13.253 2.075 1.195zm12.05 4.518h15.839v2.108h-15.839z" fill="#fff"/><path d="M383.628 82.457l7.668 13.254-2.075 1.195-7.668-13.253 2.075-1.196z" fill="#fff"/><path d="M391.296 83.653l-7.668 13.253-2.075-1.195 7.668-13.254 2.075 1.196z" fill="#fff"/><path d="M311.883 128.724c-2.144.314-4.773 3.411-7.199 6.603-2.164 2.851-4.289 5.701-3.881 7.943.824 4.817 9.256 2.214 11.498 1.777l24.354-4.675v-14.546s-5.298-1.729-8.141 0c-2.843 1.73-3.881 6.243-6.481 6.575-2.601.333-6.113-4.256-10.15-3.677z" fill="#F6A81B"/><path opacity=".1" d="M300.83 144.032l35.825-6.281v-4.26l-34.72 6.664s-1.541 2.703-1.105 3.877z" fill="#231F20"/><path fill-rule="evenodd" clip-rule="evenodd" d="M331.375 130.329c0-8.733 7.092-15.812 15.84-15.812 8.748 0 15.839 7.079 15.839 15.812 0 8.732-7.091 15.811-15.839 15.811-8.748 0-15.84-7.079-15.84-15.811zm17.503.154a3.618 3.618 0 0 0 3.343 2.231 3.613 3.613 0 0 0 2.557-1.052 3.612 3.612 0 0 0-1.166-5.893 3.623 3.623 0 0 0-3.946.777 3.607 3.607 0 0 0-.788 3.937z" fill="#FAB505"/><path opacity=".2" fill-rule="evenodd" clip-rule="evenodd" d="M363.054 130.329c0 8.732-7.091 15.811-15.839 15.811v-31.623c8.748 0 15.839 7.079 15.839 15.812zm-14.176.154a3.618 3.618 0 0 0 3.343 2.231 3.613 3.613 0 0 0 2.557-1.052 3.612 3.612 0 0 0-1.166-5.893 3.623 3.623 0 0 0-3.946.777 3.605 3.605 0 0 0-.788 3.937z" fill="#fff"/><path d="M303.809 120.637c0 18.666-15.136 33.798-33.809 33.798s-33.809-15.132-33.809-33.798c0-18.666 15.136-33.799 33.809-33.799s33.809 15.133 33.809 33.799z" fill="#fff" stroke="#F1F3F4"/></svg>
\ No newline at end of file diff --git a/chromium/chrome/browser/resources/signin/signin_reauth/images/account_passwords_reauth_illustration_dark.svg b/chromium/chrome/browser/resources/signin/signin_reauth/images/account_passwords_reauth_illustration_dark.svg new file mode 100644 index 00000000000..051afdde074 --- /dev/null +++ b/chromium/chrome/browser/resources/signin/signin_reauth/images/account_passwords_reauth_illustration_dark.svg @@ -0,0 +1 @@ +<svg width="540" height="170" viewBox="0 0 540 170" fill="none" xmlns="http://www.w3.org/2000/svg"><path opacity=".04" d="M281.956 123.563c14.58 0 26.399-.944 26.399-2.108 0-1.164-11.819-2.108-26.399-2.108s-26.399.944-26.399 2.108c0 1.164 11.819 2.108 26.399 2.108z" fill="#202124"/><path opacity=".18" d="M145.736 127.78c14.58 0 26.399-.944 26.399-2.109 0-1.164-11.819-2.108-26.399-2.108s-26.399.944-26.399 2.108c0 1.165 11.819 2.109 26.399 2.109zm156.601 13.171v4.749h45.407v-9.487l-45.407 4.738z" fill="#fff"/><path d="M278.788 116.184V54.572c0-2.65 2.123-4.797 4.741-4.797h6.875v66.409h-11.616z" fill="#303030"/><path fill-rule="evenodd" clip-rule="evenodd" d="M283.512 48.721h7.948v68.518h-13.728V54.493a5.776 5.776 0 0 1 5.78-5.772zm6.021 66.594v-64.67h-6.021a3.85 3.85 0 0 0-3.853 3.848v60.822h9.874z" fill="#5F6368"/><path d="M284.068 116.184V54.572a4.792 4.792 0 0 1 4.788-4.797h74.901a4.792 4.792 0 0 1 4.788 4.797v61.612h-84.477z" fill="#414447"/><path fill-rule="evenodd" clip-rule="evenodd" d="M288.771 48.721h75.072c3.18 0 5.758 2.584 5.758 5.772v62.746h-86.589V54.493c0-3.188 2.578-5.772 5.759-5.772zm78.911 5.772a3.843 3.843 0 0 0-3.839-3.848H288.77a3.843 3.843 0 0 0-3.839 3.848v60.822h82.751V54.493z" fill="#5F6368"/><path d="M283.549 123.563c-2.63 0-4.761-2.205-4.761-4.926v-2.453h59.134v7.379h-54.373z" fill="#303030"/><path fill-rule="evenodd" clip-rule="evenodd" d="M277.732 115.13h61.246v9.487h-55.514c-3.166 0-5.732-2.685-5.732-5.998v-3.489zm59.336 7.488v-5.488h-57.425v1.489c0 2.209 1.711 3.999 3.821 3.999h53.604z" fill="#5F6368"/><path d="M336.363 123.563c-2.638 0-4.777-2.205-4.777-4.926v-2.453h86.59v2.453c0 2.721-2.139 4.926-4.777 4.926h-77.036z" fill="#414447"/><path fill-rule="evenodd" clip-rule="evenodd" d="M330.53 115.13h88.702v3.489c0 3.313-2.574 5.998-5.748 5.998h-77.206c-3.174 0-5.748-2.685-5.748-5.998v-3.489zm86.786 3.489v-1.489h-84.87v1.489c0 2.209 1.716 3.999 3.832 3.999h77.206c2.116 0 3.832-1.79 3.832-3.999z" fill="#5F6368"/><path d="M382.925 119.347h-16.088c-.949 0-1.859-.343-2.529-.952-.67-.61-1.045-1.436-1.043-2.297v-.968h23.232v.95c.007.864-.366 1.695-1.036 2.308-.671.614-1.584.959-2.536.959z" fill="#5F6368"/><path fill="#303030" d="M290.404 57.154h70.75v52.706h-70.75z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M289.348 56.1h72.861v54.814h-72.861V56.1zm70.944 52.89V58.023h-69.027v50.967h69.027z" fill="#5F6368"/><rect x="326.307" y="81.399" width="17.951" height="1.054" rx=".527" fill="#5F6368"/><rect x="326.307" y="83.507" width="14.784" height="1.054" rx=".527" fill="#5F6368"/><rect x="160.52" y="48.721" width="55.966" height="78.004" rx="4" fill="#414447"/><path fill-rule="evenodd" clip-rule="evenodd" d="M165.166 47.667h45.618c3.149 0 5.702 2.562 5.702 5.723v68.667c0 3.161-2.553 5.723-5.702 5.723h-45.618c-3.149 0-5.702-2.562-5.702-5.723V53.39c0-3.16 2.553-5.723 5.702-5.723zm49.419 5.722a3.808 3.808 0 0 0-3.801-3.815h-45.618a3.808 3.808 0 0 0-3.802 3.815v68.668a3.808 3.808 0 0 0 3.802 3.815h45.618a3.808 3.808 0 0 0 3.801-3.815V53.389z" fill="#5F6368"/><path fill="#303030" d="M165.8 53.992h44.351v67.463H165.8z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M164.744 53.992h46.462v68.517h-46.462V53.992zm44.526 66.614V55.895h-42.59v64.711h42.59z" fill="#5F6368"/><rect x="137.289" y="67.695" width="32.735" height="59.03" rx="4" fill="#414447"/><path fill-rule="evenodd" clip-rule="evenodd" d="M142.04 66.641h23.231c3.208 0 5.808 2.566 5.808 5.732v49.675c0 3.165-2.6 5.732-5.808 5.732H142.04c-3.207 0-5.808-2.567-5.808-5.732V72.373c0-3.166 2.601-5.732 5.808-5.732zm27.103 5.732c0-2.11-1.733-3.821-3.871-3.821H142.04c-2.138 0-3.872 1.71-3.872 3.821v49.675c0 2.11 1.734 3.821 3.872 3.821h23.232c2.138 0 3.871-1.711 3.871-3.821V72.373z" fill="#5F6368"/><path fill="#5F6368" d="M136.232 76.128h34.847v2.108h-34.847zm0 42.165h34.847v2.108h-34.847z"/><path fill="#303030" d="M138.344 78.237h30.623v40.056h-30.623z"/><rect x="145.736" y="71.912" width="15.839" height="2.108" rx="1" fill="#5F6368"/><rect x="147.848" y="100.373" width="12.672" height="1.054" rx=".527" fill="#5F6368"/><rect x="148.904" y="103.535" width="10.56" height="1.054" rx=".527" fill="#5F6368"/><rect x="181.639" y="83.507" width="12.672" height="1.054" rx=".527" fill="#5F6368"/><rect x="182.695" y="86.669" width="10.56" height="1.054" rx=".527" fill="#5F6368"/><path fill-rule="evenodd" clip-rule="evenodd" d="M148.292 88.135a5.809 5.809 0 0 1 5.374-3.574 5.793 5.793 0 0 1 5.798 5.787 5.798 5.798 0 0 1-3.581 5.365 5.816 5.816 0 0 1-6.334-1.255 5.791 5.791 0 0 1-1.257-6.323zm5.374-1.838a1.735 1.735 0 1 1 1.23 2.964 1.743 1.743 0 0 1-1.896.377 1.736 1.736 0 0 1 .666-3.34zm0 8.222c-1.4.001-2.707-.7-3.479-1.866 0-1.147 2.319-1.776 3.479-1.776 1.16 0 3.469.629 3.479 1.776a4.17 4.17 0 0 1-3.479 1.866zm29.483-26.434a5.807 5.807 0 0 1 5.393-3.552 5.803 5.803 0 0 1 5.769 5.798 5.798 5.798 0 0 1-3.595 5.36 5.815 5.815 0 0 1-6.334-1.275 5.788 5.788 0 0 1-1.233-6.331zm5.393-1.81a1.741 1.741 0 1 1 1.231 2.978 1.747 1.747 0 0 1-2.976-1.245 1.734 1.734 0 0 1 1.745-1.732zm0 8.229a4.162 4.162 0 0 1-3.48-1.87c0-1.152 2.317-1.782 3.48-1.782 1.164 0 3.471.63 3.481 1.782a4.153 4.153 0 0 1-3.481 1.87z" fill="#5F6368"/><path d="M129.626 40.703c-4.229 1.222-7.12 4.922-7.121 9.115 0 .559.477 1.011 1.065 1.011.589 0 1.066-.452 1.066-1.01.001-3.304 2.278-6.22 5.611-7.182 3.333-.963 6.938.252 8.881 2.994l.441.622.755-.22a4.453 4.453 0 0 1 1.222-.175 4.29 4.29 0 0 1 2.948 1.16 3.86 3.86 0 0 1 1.223 2.8c0 .559.477 1.011 1.066 1.011.588 0 1.065-.452 1.065-1.01 0-1.587-.665-3.109-1.847-4.23-1.183-1.123-2.788-1.753-4.46-1.753a6.74 6.74 0 0 0-1.085.093c-2.545-3.072-6.841-4.379-10.83-3.226z" fill="#5F6368"/><path d="M141.604 43.45a5.845 5.845 0 0 0-4.034 1.596.888.888 0 0 0 .002 1.299.998.998 0 0 0 1.363-.002 3.868 3.868 0 0 1 2.669-1.055c.533 0 .964-.412.964-.919 0-.507-.431-.919-.964-.918zm44.229-17.528c-1.67-.002-3.277.627-4.461 1.748-1.184 1.122-1.848 2.645-1.845 4.231.001.558.479 1.01 1.068 1.009.588-.002 1.064-.454 1.063-1.012a3.843 3.843 0 0 1 1.221-2.8 4.286 4.286 0 0 1 2.954-1.156 4.5 4.5 0 0 1 1.225.169l.751.213.438-.617c1.945-2.741 5.552-3.955 8.885-2.99 3.334.963 5.61 3.88 5.607 7.182 0 .558.477 1.01 1.065 1.01.589.001 1.066-.45 1.066-1.009.004-4.191-2.885-7.892-7.116-9.116-3.991-1.154-8.292.152-10.837 3.225a6.727 6.727 0 0 0-1.084-.087z" fill="#5F6368"/><path d="M185.774 28.422a3.816 3.816 0 0 1 2.67 1.053.991.991 0 0 0 1.358.006.89.89 0 0 0 .006-1.299 5.78 5.78 0 0 0-4.046-1.597c-.531.003-.958.417-.955.924.004.508.437.916.967.913zm210.924 30.427c-3.482 0-6.306 2.676-6.306 5.977 0 .558.477 1.01 1.066 1.01.588 0 1.065-.452 1.065-1.01 0-2.185 1.87-3.957 4.177-3.957a4.5 4.5 0 0 1 1.223.168l.751.213.438-.617c1.944-2.74 5.552-3.955 8.885-2.99 3.334.964 5.61 3.88 5.607 7.182 0 .558.477 1.01 1.065 1.011.588 0 1.066-.451 1.066-1.01.004-4.19-2.885-7.891-7.116-9.115-3.991-1.155-8.292.151-10.837 3.224a6.727 6.727 0 0 0-1.084-.086z" fill="#5F6368"/><path d="M396.639 60.294a3.854 3.854 0 0 1 2.652 1.053c.377.36.991.364 1.372.007a.883.883 0 0 0 .008-1.299c-1.063-1.018-2.512-1.593-4.026-1.598-.536-.001-.972.409-.973.916-.002.507.431.92.967.921z" fill="#5F6368"/><rect x="317.178" y="74.461" width="103.485" height="30.569" rx="5.37" fill="#8AB4F8"/><rect x="403.768" y="79.731" width="2.112" height="18.974" rx="1" fill="#F28B82"/><path fill="#5F6368" d="M328.794 88.164h15.839v2.108h-15.839z"/><path d="M333.784 82.454l7.668 13.254-2.075 1.195-7.668-13.253 2.075-1.196z" fill="#5F6368"/><path d="M341.452 83.65l-7.668 13.253-2.076-1.195 7.669-13.254 2.075 1.195zm11.629 4.514h15.839v2.108h-15.839z" fill="#5F6368"/><path d="M358.706 82.45l7.668 13.254-2.075 1.196-7.668-13.254 2.075-1.195z" fill="#5F6368"/><path d="M366.374 83.646L358.706 96.9l-2.075-1.196 7.668-13.253 2.075 1.195zm12.05 4.518h15.839v2.108h-15.839z" fill="#5F6368"/><path d="M383.628 82.457l7.668 13.254-2.075 1.195-7.668-13.253 2.075-1.196z" fill="#5F6368"/><path d="M391.296 83.653l-7.668 13.253-2.075-1.195 7.668-13.254 2.075 1.196z" fill="#5F6368"/><path d="M311.883 128.724c-2.144.314-4.773 3.411-7.199 6.603-2.164 2.851-4.289 5.701-3.881 7.943.824 4.817 9.256 2.214 11.498 1.777l24.354-4.675v-14.546s-5.298-1.729-8.141 0c-2.843 1.73-3.881 6.243-6.481 6.575-2.601.333-6.113-4.256-10.15-3.677z" fill="#FED563"/><path opacity=".1" d="M300.83 144.032l35.825-6.281v-4.26l-34.72 6.664s-1.541 2.703-1.105 3.877z" fill="#231F20"/><path fill-rule="evenodd" clip-rule="evenodd" d="M331.375 130.329c0-8.733 7.092-15.812 15.84-15.812 8.748 0 15.839 7.079 15.839 15.812 0 8.732-7.091 15.811-15.839 15.811-8.748 0-15.84-7.079-15.84-15.811zm17.503.154a3.618 3.618 0 0 0 3.343 2.231 3.613 3.613 0 0 0 2.557-1.052 3.612 3.612 0 0 0-1.166-5.893 3.623 3.623 0 0 0-3.946.777 3.607 3.607 0 0 0-.788 3.937z" fill="#FED563"/><path opacity=".24" fill-rule="evenodd" clip-rule="evenodd" d="M363.054 130.329c0 8.732-7.091 15.811-15.839 15.811v-31.623c8.748 0 15.839 7.079 15.839 15.812zm-14.176.154a3.618 3.618 0 0 0 3.343 2.231 3.613 3.613 0 0 0 2.557-1.052 3.612 3.612 0 0 0-1.166-5.893 3.623 3.623 0 0 0-3.946.777 3.605 3.605 0 0 0-.788 3.937z" fill="#fff"/><path d="M303.809 120.637c0 18.666-15.136 33.798-33.809 33.798s-33.809-15.132-33.809-33.798c0-18.666 15.136-33.799 33.809-33.799s33.809 15.133 33.809 33.799z" fill="#414447" stroke="#5F6368"/></svg>
\ No newline at end of file diff --git a/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth.html b/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth.html new file mode 100644 index 00000000000..0cdd9b27b8f --- /dev/null +++ b/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth.html @@ -0,0 +1,24 @@ +<!doctype html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> + <head> + <meta charset="utf-8"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> + <style> + body { + height: 100vh; + margin: 0; + width: 100vw; + } + + @media (prefers-color-scheme: dark) { + body { + background-color: var(--google-grey-900); + } + } + </style> + </head> + <body> + <signin-reauth-app></signin-reauth-app> + <script type="module" src="signin_reauth_app.js"></script> + </body> +</html> diff --git a/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.html b/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.html new file mode 100644 index 00000000000..f6257f63261 --- /dev/null +++ b/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.html @@ -0,0 +1,87 @@ +<style include="signin-dialog-shared cr-hidden-style"> + :host { + color: var(--cr-primary-text-color); + display: flex; + flex-direction: column; + height: 100%; + } + + #illustrationContainer { + height: 170px; + position: relative; + width: 100%; + } + + #illustration { + background: url(./images/signin_reauth_illustration.svg); + background-size: 100% 100%; + height: 100%; + position: absolute; + top: 0; + width: 100%; + } + + @media (prefers-color-scheme: dark) { + #illustration { + background: url(./images/signin_reauth_illustration_dark.svg); + } + } + + #illustrationContainer > img { + border-radius: 50%; + height: 58px; + left: 0; + margin: auto; + position: absolute; + right: 0; + top: 92px; + width: 58px; + } + + #contentContainer { + flex-grow: 1; + width: 100%; + } + + h1 { + font-weight: normal; + margin-bottom: 8px; + padding: 0 40px; + } + + .message-container { + color: var(--cr-secondary-text-color); + line-height: 20px; + margin-bottom: 16px; + padding: 0 40px; + } + + cr-button { + padding-inline-end: 16px; + padding-inline-start: 16px; + } +</style> +<div id="illustrationContainer"> + <div id="illustration"></div> + <img src="[[accountImageSrc_]]"> +</div> +<div id="contentContainer"> + <h1 id="signinReauthTitle"> + $i18n{signinReauthTitle} + </h1> + <div class="message-container"> + <div>$i18n{signinReauthDesc}</div> + </div> +</div> +<div class="action-container"> + <paper-spinner-lite active hidden$="[[!confirmButtonHidden_]]"> + </paper-spinner-lite> + <cr-button id="confirmButton" class="action-button" on-click="onConfirm_" + hidden="[[confirmButtonHidden_]]"> + [[confirmButtonLabel_]] + </cr-button> + <cr-button id="cancelButton" on-click="onCancel_" + hidden="[[cancelButtonHidden_]]"> + $i18n{signinReauthCloseLabel} + </cr-button> +</div> diff --git a/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.js b/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.js new file mode 100644 index 00000000000..e2c6b4ec6d9 --- /dev/null +++ b/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.js @@ -0,0 +1,78 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/hidden_style_css.m.js'; +import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js'; +import './strings.m.js'; +import './signin_shared_css.js'; + +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {SigninReauthBrowserProxy, SigninReauthBrowserProxyImpl} from './signin_reauth_browser_proxy.js'; + +Polymer({ + is: 'signin-reauth-app', + + _template: html`{__html_template__}`, + + behaviors: [I18nBehavior, WebUIListenerBehavior], + + properties: { + /** @private */ + accountImageSrc_: { + type: String, + value() { + return loadTimeData.getString('accountImageUrl'); + }, + }, + + /** @private */ + confirmButtonLabel_: String, + + /** @private */ + confirmButtonHidden_: {type: Boolean, value: true}, + + /** @private */ + cancelButtonHidden_: {type: Boolean, value: true} + }, + + /** @private {SigninReauthBrowserProxy} */ + signinReauthBrowserProxy_: null, + + /** @override */ + attached() { + this.signinReauthBrowserProxy_ = SigninReauthBrowserProxyImpl.getInstance(); + this.addWebUIListener( + 'reauth-type-received', this.onReauthTypeReceived_.bind(this)); + this.signinReauthBrowserProxy_.initialize(); + }, + + /** @private */ + onConfirm_() { + this.signinReauthBrowserProxy_.confirm(); + }, + + /** @private */ + onCancel_() { + this.signinReauthBrowserProxy_.cancel(); + }, + + /** + * @param {boolean} requiresReauth Whether the user will be asked to + * reauthenticate after clicking on the confirm button. + * @private + */ + onReauthTypeReceived_(requiresReauth) { + this.confirmButtonHidden_ = false; + this.$.confirmButton.focus(); + this.cancelButtonHidden_ = requiresReauth; + this.confirmButtonLabel_ = requiresReauth ? + this.i18n('signinReauthNextLabel') : + this.i18n('signinReauthConfirmLabel'); + }, +}); diff --git a/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth_browser_proxy.js b/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth_browser_proxy.js new file mode 100644 index 00000000000..d4a040455aa --- /dev/null +++ b/chromium/chrome/browser/resources/signin/signin_reauth/signin_reauth_browser_proxy.js @@ -0,0 +1,47 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview A helper object used by the signin reauth dialog to + * interact with the browser. + */ +import {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; + +/** @interface */ +export class SigninReauthBrowserProxy { + /** + * Called when the app has been initialized. + */ + initialize() {} + + /** + * Called when the user confirms the signin reauth dialog. + */ + confirm() {} + + /** + * Called when the user cancels the signin reauth. + */ + cancel() {} +} + +/** @implements {SigninReauthBrowserProxy} */ +export class SigninReauthBrowserProxyImpl { + /** @override */ + initialize() { + chrome.send('initialize'); + } + + /** @override */ + confirm() { + chrome.send('confirm'); + } + + /** @override */ + cancel() { + chrome.send('cancel'); + } +} + +addSingletonGetter(SigninReauthBrowserProxyImpl); diff --git a/chromium/chrome/browser/resources/signin/signin_shared_css.html b/chromium/chrome/browser/resources/signin/signin_shared_css.html index c7de5b75449..3b31a483eb2 100644 --- a/chromium/chrome/browser/resources/signin/signin_shared_css.html +++ b/chromium/chrome/browser/resources/signin/signin_shared_css.html @@ -26,11 +26,20 @@ padding: 16px; } + cr-button + cr-button { + margin-inline-start: 8px; + } + <if expr="is_macosx or is_linux"> .action-container { flex-flow: row-reverse; justify-content: flex-start; } + + cr-button + cr-button { + margin-inline-end: 8px; + margin-inline-start: 0; + } </if> </style> </template> diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js index 04c560fac17..9fb93b71e60 100644 --- a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js +++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js @@ -7,7 +7,6 @@ import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; import {SyncConfirmationBrowserProxyImpl} from './sync_confirmation_browser_proxy.js'; function initialize() { - addWebUIListener('clear-focus', clearFocus); const syncConfirmationBrowserProxy = SyncConfirmationBrowserProxyImpl.getInstance(); // Prefer using |document.body.offsetHeight| instead of @@ -21,8 +20,4 @@ function initialize() { document.body.style.width = 'auto'; } -function clearFocus() { - document.activeElement.blur(); -} - document.addEventListener('DOMContentLoaded', initialize); diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html index d8a68eb5b90..3cc7d3045b8 100644 --- a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html +++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html @@ -16,18 +16,6 @@ width: 100%; } - cr-button:not(.action-button) { - margin-inline-start: 8px; - } - -<if expr="is_macosx or is_linux"> - /* This works together with the button-flip in signin-dialog-shared. */ - cr-button:not(.action-button) { - margin-inline-end: 8px; - margin-inline-start: 0; - } -</if> - #illustration-container { height: 168px; margin-bottom: 32px; @@ -138,7 +126,7 @@ </div> <div class="action-container"> <cr-button class="action-button" id="confirmButton" - on-click="onConfirm_" consent-confirmation> + on-click="onConfirm_" consent-confirmation autofocus> $i18n{syncConfirmationConfirmLabel} </cr-button> <cr-button id="cancelButton" on-click="onUndo_"> diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js index 1557d13bc78..83d2cccafb7 100644 --- a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js +++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js @@ -36,28 +36,15 @@ Polymer({ /** @private {?SyncConfirmationBrowserProxy} */ syncConfirmationBrowserProxy_: null, - /** @private {?function(Event)} */ - boundKeyDownHandler_: null, - /** @override */ attached() { this.syncConfirmationBrowserProxy_ = SyncConfirmationBrowserProxyImpl.getInstance(); - this.boundKeyDownHandler_ = this.onKeyDown_.bind(this); - // This needs to be bound to document instead of "this" because the dialog - // window opens initially, the focus level is only on document, so the key - // event is not captured by "this". - document.addEventListener('keydown', this.boundKeyDownHandler_); this.addWebUIListener( 'account-image-changed', this.handleAccountImageChanged_.bind(this)); this.syncConfirmationBrowserProxy_.requestAccountImage(); }, - /** @override */ - detached() { - document.removeEventListener('keydown', this.boundKeyDownHandler_); - }, - /** @private */ onConfirm_(e) { this.syncConfirmationBrowserProxy_.confirm( @@ -75,14 +62,6 @@ Polymer({ this.getConsentDescription_(), this.getConsentConfirmation_(e.path)); }, - /** @private */ - onKeyDown_(e) { - if (e.key == 'Enter' && !/^(A|CR-BUTTON)$/.test(e.path[0].tagName)) { - this.onConfirm_(e); - e.preventDefault(); - } - }, - /** * @param {!Array<!HTMLElement>} path Path of the click event. Must contain * a consent confirmation element. diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.html b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.html index 4ec21e8f6d3..c0b206c5bff 100644 --- a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.html +++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.html @@ -2,14 +2,6 @@ .details { padding: 0 24px; } - #undoButton { -<if expr="is_macosx or is_linux"> - margin-inline-end: 8px; -</if> -<if expr="not is_macosx and not is_linux"> - margin-inline-start: 8px; -</if> - } #syncDisabledDetails { line-height: 20px; diff --git a/chromium/chrome/browser/resources/tab_strip/drag_manager.js b/chromium/chrome/browser/resources/tab_strip/drag_manager.js index 69b836bf742..b50733200f8 100644 --- a/chromium/chrome/browser/resources/tab_strip/drag_manager.js +++ b/chromium/chrome/browser/resources/tab_strip/drag_manager.js @@ -9,7 +9,7 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {isTabElement, TabElement} from './tab.js'; import {isTabGroupElement, TabGroupElement} from './tab_group.js'; -import {TabData, TabNetworkState, TabsApiProxy} from './tabs_api_proxy.js'; +import {TabData, TabNetworkState, TabsApiProxy, TabsApiProxyImpl} from './tabs_api_proxy.js'; /** @const {number} */ export const PLACEHOLDER_TAB_ID = -1; @@ -107,7 +107,7 @@ class DragSession { this.srcGroup = srcGroup; /** @private @const {!TabsApiProxy} */ - this.tabsProxy_ = TabsApiProxy.getInstance(); + this.tabsProxy_ = TabsApiProxyImpl.getInstance(); } /** @@ -359,7 +359,8 @@ class DragSession { const dragOverTabElement = /** @type {!TabElement|undefined} */ (composedPath.find(isTabElement)); - if (dragOverTabElement && !dragOverTabElement.tab.pinned) { + if (dragOverTabElement && !dragOverTabElement.tab.pinned && + dragOverTabElement.isValidDragOverTarget) { let dragOverIndex = this.delegate_.getIndexOfTab(dragOverTabElement); dragOverIndex += this.shouldOffsetIndexForGroup_(dragOverTabElement) ? 1 : 0; @@ -369,7 +370,7 @@ class DragSession { const dragOverGroupElement = /** @type {!TabGroupElement|undefined} */ ( composedPath.find(isTabGroupElement)); - if (dragOverGroupElement) { + if (dragOverGroupElement && dragOverGroupElement.isValidDragOverTarget) { let dragOverIndex = this.delegate_.getIndexOfTab( /** @type {!TabElement} */ (dragOverGroupElement.firstElementChild)); dragOverIndex += @@ -388,8 +389,9 @@ class DragSession { const dragOverTabElement = /** @type {?TabElement} */ (composedPath.find(isTabElement)); if (dragOverTabElement && - dragOverTabElement.tab.pinned !== tabElement.tab.pinned) { - // Can only drag between the same pinned states. + (dragOverTabElement.tab.pinned !== tabElement.tab.pinned || + !dragOverTabElement.isValidDragOverTarget)) { + // Can only drag between the same pinned states and valid TabElements. return; } @@ -401,7 +403,8 @@ class DragSession { const dragOverTabGroup = /** @type {?TabGroupElement} */ (composedPath.find(isTabGroupElement)); if (dragOverTabGroup && - dragOverTabGroup.dataset.groupId !== previousGroupId) { + dragOverTabGroup.dataset.groupId !== previousGroupId && + dragOverTabGroup.isValidDragOverTarget) { this.delegate_.placeTabElement( tabElement, this.dstIndex, false, dragOverTabGroup.dataset.groupId); return; @@ -433,7 +436,7 @@ export class DragManager { this.dragSession_ = null; /** @private {!TabsApiProxy} */ - this.tabsProxy_ = TabsApiProxy.getInstance(); + this.tabsProxy_ = TabsApiProxyImpl.getInstance(); } /** @private */ diff --git a/chromium/chrome/browser/resources/tab_strip/tab.js b/chromium/chrome/browser/resources/tab_strip/tab.js index 4c6fbb904e1..61da08df076 100644 --- a/chromium/chrome/browser/resources/tab_strip/tab.js +++ b/chromium/chrome/browser/resources/tab_strip/tab.js @@ -11,10 +11,10 @@ import {isRTL} from 'chrome://resources/js/util.m.js'; import {AlertIndicatorsElement} from './alert_indicators.js'; import {CustomElement} from './custom_element.js'; -import {TabStripEmbedderProxy} from './tab_strip_embedder_proxy.js'; +import {TabStripEmbedderProxy, TabStripEmbedderProxyImpl} from './tab_strip_embedder_proxy.js'; import {tabStripOptions} from './tab_strip_options.js'; import {TabSwiper} from './tab_swiper.js'; -import {CloseTabAction, TabData, TabNetworkState, TabsApiProxy} from './tabs_api_proxy.js'; +import {CloseTabAction, TabData, TabNetworkState, TabsApiProxy, TabsApiProxyImpl} from './tabs_api_proxy.js'; const DEFAULT_ANIMATION_DURATION = 125; @@ -84,14 +84,22 @@ export class TabElement extends CustomElement { this.tab_; /** @private {!TabsApiProxy} */ - this.tabsApi_ = TabsApiProxy.getInstance(); + this.tabsApi_ = TabsApiProxyImpl.getInstance(); /** @private {!TabStripEmbedderProxy} */ - this.embedderApi_ = TabStripEmbedderProxy.getInstance(); + this.embedderApi_ = TabStripEmbedderProxyImpl.getInstance(); /** @private {!HTMLElement} */ this.titleTextEl_ = /** @type {!HTMLElement} */ (this.$('#titleText')); + /** + * Flag indicating if this TabElement can accept dragover events. This + * is used to pause dragover events while animating as animating causes + * the elements below the pointer to shift. + * @private {boolean} + */ + this.isValidDragOverTarget_ = true; + this.tabEl_.addEventListener('click', () => this.onClick_()); this.tabEl_.addEventListener('contextmenu', e => this.onContextMenu_(e)); this.tabEl_.addEventListener( @@ -169,6 +177,16 @@ export class TabElement extends CustomElement { this.tab_ = Object.freeze(tab); } + /** @return {boolean} */ + get isValidDragOverTarget() { + return !this.hasAttribute('dragging_') && this.isValidDragOverTarget_; + } + + /** @param {boolean} isValid */ + set isValidDragOverTarget(isValid) { + this.isValidDragOverTarget_ = isValid; + } + /** @param {!Function} callback */ set onTabActivating(callback) { this.onTabActivating_ = callback; diff --git a/chromium/chrome/browser/resources/tab_strip/tab_group.js b/chromium/chrome/browser/resources/tab_strip/tab_group.js index e50abdbf55a..cfd47a53868 100644 --- a/chromium/chrome/browser/resources/tab_strip/tab_group.js +++ b/chromium/chrome/browser/resources/tab_strip/tab_group.js @@ -5,7 +5,7 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {CustomElement} from './custom_element.js'; -import {TabStripEmbedderProxy} from './tab_strip_embedder_proxy.js'; +import {TabStripEmbedderProxy, TabStripEmbedderProxyImpl} from './tab_strip_embedder_proxy.js'; import {TabGroupVisualData} from './tabs_api_proxy.js'; export class TabGroupElement extends CustomElement { @@ -17,13 +17,30 @@ export class TabGroupElement extends CustomElement { super(); /** @private @const {!TabStripEmbedderProxy} */ - this.embedderApi_ = TabStripEmbedderProxy.getInstance(); + this.embedderApi_ = TabStripEmbedderProxyImpl.getInstance(); /** @private @const {!HTMLElement} */ this.chip_ = /** @type {!HTMLElement} */ (this.$('#chip')); this.chip_.addEventListener('click', () => this.onClickChip_()); this.chip_.addEventListener( 'keydown', e => this.onKeydownChip_(/** @type {!KeyboardEvent} */ (e))); + + /** + * Flag indicating if this element can accept dragover events. This flag + * is updated by TabListElement while animating. + * @private {boolean} + */ + this.isValidDragOverTarget_ = true; + } + + /** @return {boolean} */ + get isValidDragOverTarget() { + return !this.hasAttribute('dragging_') && this.isValidDragOverTarget_; + } + + /** @param {boolean} isValid */ + set isValidDragOverTarget(isValid) { + this.isValidDragOverTarget_ = isValid; } /** @return {!HTMLElement} */ diff --git a/chromium/chrome/browser/resources/tab_strip/tab_list.html b/chromium/chrome/browser/resources/tab_strip/tab_list.html index 12be60a5f39..f6cb511ab76 100644 --- a/chromium/chrome/browser/resources/tab_strip/tab_list.html +++ b/chromium/chrome/browser/resources/tab_strip/tab_list.html @@ -41,11 +41,12 @@ * tab. 20px is subtracted from the height of an unpinned tab as there * are two 10px gaps to separate each of the 3 pinned tabs. */ --tabstrip-pinned-tab-size: calc((var(--tabstrip-tab-height) - 20px) / 3); + --tabstrip-tab-spacing: 10px; display: grid; grid-auto-columns: var(--tabstrip-pinned-tab-size); grid-auto-flow: column; - grid-gap: 10px; + grid-gap: var(--tabstrip-tab-spacing); grid-template-rows: repeat(3, var(--tabstrip-pinned-tab-size)); padding-block-end: var(--tabstrip-tab-list-vertical-padding); padding-block-start: var(--tabstrip-tab-list-vertical-padding); diff --git a/chromium/chrome/browser/resources/tab_strip/tab_list.js b/chromium/chrome/browser/resources/tab_strip/tab_list.js index 08ac72db837..5ab5de62076 100644 --- a/chromium/chrome/browser/resources/tab_strip/tab_list.js +++ b/chromium/chrome/browser/resources/tab_strip/tab_list.js @@ -15,11 +15,11 @@ import {isRTL} from 'chrome://resources/js/util.m.js'; import {CustomElement} from './custom_element.js'; import {DragManager, DragManagerDelegate} from './drag_manager.js'; -import {TabElement} from './tab.js'; +import {isTabElement, TabElement} from './tab.js'; import {isTabGroupElement, TabGroupElement} from './tab_group.js'; -import {TabStripEmbedderProxy} from './tab_strip_embedder_proxy.js'; +import {TabStripEmbedderProxy, TabStripEmbedderProxyImpl} from './tab_strip_embedder_proxy.js'; import {tabStripOptions} from './tab_strip_options.js'; -import {TabData, TabGroupVisualData, TabsApiProxy} from './tabs_api_proxy.js'; +import {TabData, TabGroupVisualData, TabsApiProxy, TabsApiProxyImpl} from './tabs_api_proxy.js'; /** * The amount of padding to leave between the edge of the screen and the active @@ -47,8 +47,88 @@ const LayoutVariable = { TAB_WIDTH: '--tabstrip-tab-thumbnail-width', }; +/** + * Animates a series of elements to indicate that tabs have moved position. + * @param {!Element} movedElement + * @param {number} prevIndex + * @param {number} newIndex + */ +function animateElementMoved(movedElement, prevIndex, newIndex) { + // Direction is -1 for moving towards a lower index, +1 for moving + // towards a higher index. If moving towards a lower index, the TabList needs + // to animate everything from the movedElement's current index to its prev + // index by traversing the nextElementSibling of each element because the + // movedElement is now at a preceding position from all the elements it has + // slid across. If moving towards a higher index, the TabList needs to + // traverse the previousElementSiblings. + const direction = Math.sign(newIndex - prevIndex); + + /** + * @param {!Element} element + * @return {?Element} + */ + function getSiblingToAnimate(element) { + return direction === -1 ? element.nextElementSibling : + element.previousElementSibling; + } + let elementToAnimate = getSiblingToAnimate(movedElement); + for (let i = newIndex; i !== prevIndex && elementToAnimate; i -= direction) { + const elementToAnimatePrevIndex = i; + const elementToAnimateNewIndex = i - direction; + slideElement( + elementToAnimate, elementToAnimatePrevIndex, elementToAnimateNewIndex); + elementToAnimate = getSiblingToAnimate(elementToAnimate); + } + + slideElement(movedElement, prevIndex, newIndex); +} + +/** + * Animates the slide of an element across the tab strip (both vertically and + * horizontally for pinned tabs, and horizontally for other tabs and groups). + * @param {!Element} element + * @param {number} prevIndex + * @param {number} newIndex + */ +function slideElement(element, prevIndex, newIndex) { + let horizontalMovement = newIndex - prevIndex; + let verticalMovement = 0; + + if (isTabElement(element) && element.tab.pinned) { + const pinnedTabsPerColumn = 3; + const columnChange = Math.floor(newIndex / pinnedTabsPerColumn) - + Math.floor(prevIndex / pinnedTabsPerColumn); + horizontalMovement = columnChange; + verticalMovement = + (newIndex - prevIndex) - (columnChange * pinnedTabsPerColumn); + } + + horizontalMovement *= isRTL() ? -1 : 1; + + const translateX = `calc(${horizontalMovement * -1} * ` + + '(var(--tabstrip-tab-width) + var(--tabstrip-tab-spacing)))'; + const translateY = `calc(${verticalMovement * -1} * ` + + '(var(--tabstrip-tab-height) + var(--tabstrip-tab-spacing)))'; + + element.isValidDragOverTarget = false; + const animation = element.animate( + [ + {transform: `translate(${translateX}, ${translateY})`}, + {transform: 'translate(0, 0)'}, + ], + { + duration: 120, + easing: 'ease-out', + }); + function onComplete() { + element.isValidDragOverTarget = true; + } + animation.oncancel = onComplete; + animation.onfinish = onComplete; +} + /** @implements {DragManagerDelegate} */ -class TabListElement extends CustomElement { +export class TabListElement extends CustomElement { static get template() { return `{__html_template__}`; } @@ -122,10 +202,10 @@ class TabListElement extends CustomElement { this.pinnedTabsElement_ = /** @type {!Element} */ (this.$('#pinnedTabs')); /** @private {!TabStripEmbedderProxy} */ - this.tabStripEmbedderProxy_ = TabStripEmbedderProxy.getInstance(); + this.tabStripEmbedderProxy_ = TabStripEmbedderProxyImpl.getInstance(); /** @private {!TabsApiProxy} */ - this.tabsApi_ = TabsApiProxy.getInstance(); + this.tabsApi_ = TabsApiProxyImpl.getInstance(); /** @private {!Element} */ this.unpinnedTabsElement_ = @@ -265,7 +345,9 @@ class TabListElement extends CustomElement { this.addWebUIListener_('tab-created', tab => this.onTabCreated_(tab)); this.addWebUIListener_( - 'tab-moved', (tabId, newIndex) => this.onTabMoved_(tabId, newIndex)); + 'tab-moved', + (tabId, newIndex, pinned) => + this.onTabMoved_(tabId, newIndex, pinned)); this.addWebUIListener_('tab-removed', tabId => this.onTabRemoved_(tabId)); this.addWebUIListener_( 'tab-replaced', (oldId, newId) => this.onTabReplaced_(oldId, newId)); @@ -556,13 +638,13 @@ class TabListElement extends CustomElement { /** * @param {number} tabId * @param {number} newIndex + * @param {boolean} pinned * @private */ - onTabMoved_(tabId, newIndex) { + onTabMoved_(tabId, newIndex, pinned) { const movedTab = this.findTabElement_(tabId); if (movedTab) { - this.placeTabElement( - movedTab, newIndex, movedTab.tab.pinned, movedTab.tab.groupId); + this.placeTabElement(movedTab, newIndex, pinned, movedTab.tab.groupId); if (movedTab.tab.active) { this.scrollToTab_(movedTab); } @@ -638,50 +720,14 @@ class TabListElement extends CustomElement { placeTabElement(element, index, pinned, groupId) { const isInserting = !element.isConnected; - // Remove the element if it already exists in the DOM. - element.remove(); - - if (pinned) { - this.pinnedTabsElement_.insertBefore( - element, this.pinnedTabsElement_.childNodes[index]); - } else { - let elementToInsert = element; - let elementAtIndex = this.$all('tabstrip-tab').item(index); - let parentElement = this.unpinnedTabsElement_; - - if (groupId) { - let tabGroupElement = this.findTabGroupElement_(groupId); - if (tabGroupElement) { - // If a TabGroupElement already exists, add the TabElement to it. - parentElement = tabGroupElement; - } else { - // If a TabGroupElement does not exist, create one and add the - // TabGroupElement into the DOM. - tabGroupElement = document.createElement('tabstrip-tab-group'); - tabGroupElement.setAttribute('data-group-id', groupId); - tabGroupElement.appendChild(element); - elementToInsert = tabGroupElement; - } - } - - if (elementAtIndex && elementAtIndex.parentElement && - isTabGroupElement(elementAtIndex.parentElement) && - (elementAtIndex.previousElementSibling === null && - elementAtIndex.tab.groupId !== groupId)) { - // If the element at the model index is in a group, and the group is - // different from the new tab's group, and is the first element in its - // group, insert the new element before its TabGroupElement. If a - // TabElement is being sandwiched between two TabElements in a group, it - // can be assumed that the tab will eventually be inserted into the - // group as well. - elementAtIndex = elementAtIndex.parentElement; - } + const previousIndex = isInserting ? -1 : this.getIndexOfTab(element); + const previousParent = element.parentElement; + this.updateTabElementDomPosition_(element, index, pinned, groupId); - if (elementAtIndex && elementAtIndex.parentElement === parentElement) { - parentElement.insertBefore(elementToInsert, elementAtIndex); - } else { - parentElement.appendChild(elementToInsert); - } + if (!isInserting && previousParent === element.parentElement) { + // Only animate if the tab is being moved within the same parent. Tab + // moves that change pinned state or grouped states do not animate. + animateElementMoved(element, previousIndex, index); } if (isInserting) { @@ -694,7 +740,15 @@ class TabListElement extends CustomElement { * @param {number} index */ placeTabGroupElement(element, index) { - element.remove(); + const previousDomIndex = + Array.from(this.unpinnedTabsElement_.children).indexOf(element); + if (element.isConnected && element.childElementCount && + this.getIndexOfTab( + /** @type {!TabElement} */ (element.firstElementChild)) < index) { + // If moving after its original position, the index value needs to be + // offset by 1 to consider itself already attached to the DOM. + index++; + } let elementAtIndex = this.$all('tabstrip-tab')[index]; if (elementAtIndex && elementAtIndex.parentElement && @@ -703,6 +757,14 @@ class TabListElement extends CustomElement { } this.unpinnedTabsElement_.insertBefore(element, elementAtIndex); + + // Animating the TabGroupElement move should be treated the same as + // animating a TabElement. Therefore, treat indices as if they were mere + // tabs and do not use the group's model index as they are not as accurate + // in representing DOM movements. + animateElementMoved( + element, previousDomIndex, + Array.from(this.unpinnedTabsElement_.children).indexOf(element)); } /** @private */ @@ -775,6 +837,63 @@ class TabListElement extends CustomElement { } /** + * @param {!TabElement} element + * @param {number} index + * @param {boolean} pinned + * @param {string=} groupId + * @private + */ + updateTabElementDomPosition_(element, index, pinned, groupId) { + // Remove the element if it already exists in the DOM. This simplifies + // the way indices work as it does not have to count its old index in + // the initial layout of the DOM. + element.remove(); + + if (pinned) { + this.pinnedTabsElement_.insertBefore( + element, this.pinnedTabsElement_.childNodes[index]); + } else { + let elementToInsert = element; + let elementAtIndex = this.$all('tabstrip-tab').item(index); + let parentElement = this.unpinnedTabsElement_; + + if (groupId) { + let tabGroupElement = this.findTabGroupElement_(groupId); + if (tabGroupElement) { + // If a TabGroupElement already exists, add the TabElement to it. + parentElement = tabGroupElement; + } else { + // If a TabGroupElement does not exist, create one and add the + // TabGroupElement into the DOM. + tabGroupElement = document.createElement('tabstrip-tab-group'); + tabGroupElement.setAttribute('data-group-id', groupId); + tabGroupElement.appendChild(element); + elementToInsert = tabGroupElement; + } + } + + if (elementAtIndex && elementAtIndex.parentElement && + isTabGroupElement(elementAtIndex.parentElement) && + (elementAtIndex.previousElementSibling === null && + elementAtIndex.tab.groupId !== groupId)) { + // If the element at the model index is in a group, and the group is + // different from the new tab's group, and is the first element in its + // group, insert the new element before its TabGroupElement. If a + // TabElement is being sandwiched between two TabElements in a group, it + // can be assumed that the tab will eventually be inserted into the + // group as well. + elementAtIndex = elementAtIndex.parentElement; + } + + if (elementAtIndex && elementAtIndex.parentElement === parentElement) { + parentElement.insertBefore(elementToInsert, elementAtIndex); + } else { + parentElement.appendChild(elementToInsert); + } + } + } + + /** * @param {!TabElement} tabElement * @private */ diff --git a/chromium/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js b/chromium/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js index 898858e782c..3bfcc59f238 100644 --- a/chromium/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js +++ b/chromium/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js @@ -4,31 +4,24 @@ import {addSingletonGetter, addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +/** @interface */ export class TabStripEmbedderProxy { /** @return {boolean} */ - isVisible() { - return document.visibilityState === 'visible'; - } + isVisible() {} /** * @return {!Promise<!Object<string, string>>} Object with CSS variables * as keys and rgba strings as values */ - getColors() { - return sendWithPromise('getThemeColors'); - } + getColors() {} /** * @return {!Promise<!Object<string, string>>} Object with CSS variables * as keys and pixel lengths as values */ - getLayout() { - return sendWithPromise('getLayout'); - } + getLayout() {} - observeThemeChanges() { - chrome.send('observeThemeChanges'); - } + observeThemeChanges() {} /** * @param {string} groupId @@ -37,53 +30,97 @@ export class TabStripEmbedderProxy { * @param {number} width * @param {number} height */ - showEditDialogForGroup(groupId, locationX, locationY, width, height) { - chrome.send( - 'showEditDialogForGroup', - [groupId, locationX, locationY, width, height]); - } + showEditDialogForGroup(groupId, locationX, locationY, width, height) {} /** * @param {number} tabId * @param {number} locationX * @param {number} locationY */ - showTabContextMenu(tabId, locationX, locationY) { - chrome.send('showTabContextMenu', [tabId, locationX, locationY]); - } + showTabContextMenu(tabId, locationX, locationY) {} /** * @param {number} locationX * @param {number} locationY */ + showBackgroundContextMenu(locationX, locationY) {} + + closeContainer() {} + + /** @param {number} durationMs Activation duration time in ms. */ + reportTabActivationDuration(durationMs) {} + + /** + * @param {number} tabCount Number of tabs. + * @param {number} durationMs Activation duration time in ms. + */ + reportTabDataReceivedDuration(tabCount, durationMs) {} + + /** + * @param {number} tabCount Number of tabs. + * @param {number} durationMs Creation duration time in ms. + */ + reportTabCreationDuration(tabCount, durationMs) {} +} + +/** @implements {TabStripEmbedderProxy} */ +export class TabStripEmbedderProxyImpl { + /** @override */ + isVisible() { + return document.visibilityState === 'visible'; + } + + /** @override */ + getColors() { + return sendWithPromise('getThemeColors'); + } + + /** @override */ + getLayout() { + return sendWithPromise('getLayout'); + } + + /** @override */ + observeThemeChanges() { + chrome.send('observeThemeChanges'); + } + + /** @override */ + showEditDialogForGroup(groupId, locationX, locationY, width, height) { + chrome.send( + 'showEditDialogForGroup', + [groupId, locationX, locationY, width, height]); + } + + /** @override */ + showTabContextMenu(tabId, locationX, locationY) { + chrome.send('showTabContextMenu', [tabId, locationX, locationY]); + } + + /** @override */ showBackgroundContextMenu(locationX, locationY) { chrome.send('showBackgroundContextMenu', [locationX, locationY]); } + /** @override */ closeContainer() { chrome.send('closeContainer'); } - /** @param {number} durationMs Activation duration time in ms. */ + /** @override */ reportTabActivationDuration(durationMs) { chrome.send('reportTabActivationDuration', [durationMs]); } - /** - * @param {number} tabCount Number of tabs. - * @param {number} durationMs Activation duration time in ms. - */ + /** @override */ reportTabDataReceivedDuration(tabCount, durationMs) { chrome.send('reportTabDataReceivedDuration', [tabCount, durationMs]); } - /** - * @param {number} tabCount Number of tabs. - * @param {number} durationMs Creation duration time in ms. - */ + /** @override */ reportTabCreationDuration(tabCount, durationMs) { chrome.send('reportTabCreationDuration', [tabCount, durationMs]); } } -addSingletonGetter(TabStripEmbedderProxy); +addSingletonGetter(TabStripEmbedderProxyImpl); diff --git a/chromium/chrome/browser/resources/tab_strip/tab_strip_resources.grd b/chromium/chrome/browser/resources/tab_strip/tab_strip_resources.grd index fe3ddc57f85..64fb60b1810 100644 --- a/chromium/chrome/browser/resources/tab_strip/tab_strip_resources.grd +++ b/chromium/chrome/browser/resources/tab_strip/tab_strip_resources.grd @@ -16,69 +16,57 @@ name="IDR_TAB_STRIP_HTML" file="tab_strip.html" type="chrome_html" - compress="gzip" preprocess="true"/> <structure name="IDR_TAB_STRIP_TABS_API_PROXY_JS" file="tabs_api_proxy.js" - type="chrome_html" - compress="gzip"/> + type="chrome_html"/> <structure name="IDR_TAB_STRIP_CUSTOM_ELEMENT_JS" file="custom_element.js" - type="chrome_html" - compress="gzip"/> + type="chrome_html"/> <structure name="IDR_TAB_STRIP_TAB_GROUP_JS" file="${root_gen_dir}/chrome/browser/resources/tab_strip/tab_group.js" use_base_dir="false" - type="chrome_html" - compress="gzip"/> + type="chrome_html"/> <structure name="IDR_TAB_STRIP_TAB_LIST_JS" file="${root_gen_dir}/chrome/browser/resources/tab_strip/tab_list.js" use_base_dir="false" type="chrome_html" - compress="gzip" preprocess="true"/> <structure name="IDR_TAB_STRIP_TAB_JS" file="${root_gen_dir}/chrome/browser/resources/tab_strip/tab.js" use_base_dir="false" - type="chrome_html" - compress="gzip"/> + type="chrome_html"/> <structure name="IDR_TAB_STRIP_ALERT_INDICATOR_JS" file="${root_gen_dir}/chrome/browser/resources/tab_strip/alert_indicator.js" use_base_dir="false" - type="chrome_html" - compress="gzip"/> + type="chrome_html"/> <structure name="IDR_TAB_STRIP_ALERT_INDICATORS_JS" file="${root_gen_dir}/chrome/browser/resources/tab_strip/alert_indicators.js" use_base_dir="false" - type="chrome_html" - compress="gzip"/> + type="chrome_html"/> <structure name="IDR_TAB_STRIP_EMBEDDER_PROXY_JS" file="tab_strip_embedder_proxy.js" - type="chrome_html" - compress="gzip"/> + type="chrome_html"/> <structure name="IDR_TAB_STRIP_OPTIONS_JS" file="tab_strip_options.js" - type="chrome_html" - compress="gzip"/> + type="chrome_html"/> <structure name="IDR_TAB_STRIP_TAB_SWIPER_JS" file="tab_swiper.js" - type="chrome_html" - compress="gzip"/> + type="chrome_html"/> <structure name="IDR_TAB_STRIP_DRAG_MANAGER_JS" file="drag_manager.js" type="chrome_html" - compress="gzip" preprocess="true"/> </structures> @@ -87,53 +75,43 @@ <include name="IDR_TAB_STRIP_PICTURE_IN_PICTURE_ALT_SVG" file="alert_indicators/picture_in_picture_alt.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_TAB_STRIP_SERIAL_PORT_SVG" file="alert_indicators/serial_port.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_TAB_STRIP_TAB_AUDIO_MUTING_ROUNDED_SVG" file="alert_indicators/tab_audio_muting_rounded.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_TAB_STRIP_TAB_AUDIO_ROUNDED_SVG" file="alert_indicators/tab_audio_rounded.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_TAB_STRIP_TAB_BLUETOOTH_CONNECTED_SVG" file="alert_indicators/tab_bluetooth_connected.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_TAB_STRIP_TAB_HID_CONNECTED_SVG" file="alert_indicators/tab_hid_connected.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_TAB_STRIP_TAB_MEDIA_CAPTURING_WITH_ARROW_SVG" file="alert_indicators/tab_media_capturing_with_arrow.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_TAB_STRIP_TAB_MEDIA_RECORING_SVG" file="alert_indicators/tab_media_recording.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_TAB_STRIP_TAB_USB_CONNECTED_SVG" file="alert_indicators/tab_usb_connected.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_TAB_STRIP_VR_HEADSET_SVG" file="alert_indicators/vr_headset.svg" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/tab_strip/tabs_api_proxy.js b/chromium/chrome/browser/resources/tab_strip/tabs_api_proxy.js index a2faa8074d7..b691666cc5a 100644 --- a/chromium/chrome/browser/resources/tab_strip/tabs_api_proxy.js +++ b/chromium/chrome/browser/resources/tab_strip/tabs_api_proxy.js @@ -67,7 +67,7 @@ export const TabAlertState = { export let TabData; /** @typedef {!Tab} */ -let ExtensionsApiTab; +export let ExtensionsApiTab; /** * @typedef {{ @@ -78,40 +78,86 @@ let ExtensionsApiTab; */ export let TabGroupVisualData; +/** @interface */ export class TabsApiProxy { /** * @param {number} tabId * @return {!Promise<!ExtensionsApiTab>} */ + activateTab(tabId) {} + + createNewTab() {} + + /** + * @return {!Promise<!Object<!TabGroupVisualData>>} Object of group IDs as + * strings mapped to their visual data. + */ + getGroupVisualData() {} + + /** + * @return {!Promise<!Array<!TabData>>} + */ + getTabs() {} + + /** + * @param {number} tabId + * @param {!CloseTabAction} closeTabAction + */ + closeTab(tabId, closeTabAction) {} + + /** + * @param {number} tabId + * @param {string} groupId + */ + groupTab(tabId, groupId) {} + + /** + * @param {string} groupId + * @param {number} newIndex + */ + moveGroup(groupId, newIndex) {} + + /** + * @param {number} tabId + * @param {number} newIndex + */ + moveTab(tabId, newIndex) {} + + /** + * @param {number} tabId + * @param {boolean} thumbnailTracked + */ + setThumbnailTracked(tabId, thumbnailTracked) {} + + /** @param {number} tabId */ + ungroupTab(tabId) {} +} + +/** @implements {TabsApiProxy} */ +export class TabsApiProxyImpl { + /** @override */ activateTab(tabId) { return new Promise(resolve => { chrome.tabs.update(tabId, {active: true}, resolve); }); } + /** @override */ createNewTab() { chrome.send('createNewTab'); } - /** - * @return {!Promise<!Object<!TabGroupVisualData>>} Object of group IDs as - * strings mapped to their visual data. - */ + /** @override */ getGroupVisualData() { return sendWithPromise('getGroupVisualData'); } - /** - * @return {!Promise<!Array<!TabData>>} - */ + /** @override */ getTabs() { return sendWithPromise('getTabs'); } - /** - * @param {number} tabId - * @param {!CloseTabAction} closeTabAction - */ + /** @override */ closeTab(tabId, closeTabAction) { chrome.send( 'closeTab', [tabId, closeTabAction === CloseTabAction.SWIPED_TO_CLOSE]); @@ -120,42 +166,30 @@ export class TabsApiProxy { Object.keys(CloseTabAction).length); } - /** - * @param {number} tabId - * @param {string} groupId - */ + /** @override */ groupTab(tabId, groupId) { chrome.send('groupTab', [tabId, groupId]); } - /** - * @param {string} groupId - * @param {number} newIndex - */ + /** @override */ moveGroup(groupId, newIndex) { chrome.send('moveGroup', [groupId, newIndex]); } - /** - * @param {number} tabId - * @param {number} newIndex - */ + /** @override */ moveTab(tabId, newIndex) { chrome.send('moveTab', [tabId, newIndex]); } - /** - * @param {number} tabId - * @param {boolean} thumbnailTracked - */ + /** @override */ setThumbnailTracked(tabId, thumbnailTracked) { chrome.send('setThumbnailTracked', [tabId, thumbnailTracked]); } - /** @param {number} tabId */ + /** @override */ ungroupTab(tabId) { chrome.send('ungroupTab', [tabId]); } } -addSingletonGetter(TabsApiProxy); +addSingletonGetter(TabsApiProxyImpl); diff --git a/chromium/chrome/browser/resources/tools/rollup_plugin.js b/chromium/chrome/browser/resources/tools/rollup_plugin.js index d6c49bf8164..c70fe31f001 100644 --- a/chromium/chrome/browser/resources/tools/rollup_plugin.js +++ b/chromium/chrome/browser/resources/tools/rollup_plugin.js @@ -9,6 +9,8 @@ const path = require('path'); const chromeResourcesUrl = 'chrome://resources/'; const polymerUrl = 'chrome://resources/polymer/v3_0/'; +const schemeRelativeResourcesUrl = '//resources/'; +const schemeRelativePolymerUrl = '//resources/polymer/v3_0/'; // TODO: Determine whether it is worth maintaining this list vs always checking // both directories for the existence of a file. @@ -19,6 +21,7 @@ const nonGeneratedFiles = [ 'certificates_browser_proxy.js', 'cr.m.js', 'cr_splitter.js', + 'plural_string_proxy.js', ]; function normalizeSlashes(filepath) { @@ -66,6 +69,8 @@ export default function plugin(srcPath, genPath, rootPath, host, excludes) { let pathFromPolymer = ''; if (source.startsWith(polymerUrl)) { pathFromPolymer = source.slice(polymerUrl.length); + } else if (source.startsWith(schemeRelativePolymerUrl)) { + pathFromPolymer = source.slice(schemeRelativePolymerUrl.length); } else if (!!origin && origin.startsWith(polymerSrcPath)) { pathFromPolymer = combinePaths(relativePath(polymerSrcPath, origin), source); @@ -82,6 +87,8 @@ export default function plugin(srcPath, genPath, rootPath, host, excludes) { let pathFromResources = ''; if (source.startsWith(chromeResourcesUrl)) { pathFromResources = source.slice(chromeResourcesUrl.length); + } else if (source.startsWith(schemeRelativeResourcesUrl)) { + pathFromResources = source.slice(schemeRelativeResourcesUrl.length); } else if (!!origin && origin.startsWith(resourcesSrcPath)) { pathFromResources = combinePaths(relativePath(resourcesSrcPath, origin), source); diff --git a/chromium/chrome/browser/resources/unpack_pak.py b/chromium/chrome/browser/resources/unpack_pak.py index d0c6ef69332..24b1d5f29d6 100755 --- a/chromium/chrome/browser/resources/unpack_pak.py +++ b/chromium/chrome/browser/resources/unpack_pak.py @@ -24,18 +24,31 @@ from grit.format import data_pack def ParseLine(line): return re.match(' {"([^"]+)", ([^},]+)', line) -def GetFileAndDirName(out_path, pak_dir, resource_path): - dirname = os.path.dirname(resource_path) - # When files are generated, |dirname| becomes - # @out_folder@/<gen_path>/path_to_resource. To make the structure look as if - # this file was not generated, remove @out_folder@ and <gen_path>. - if ('@out_folder@' in dirname): - dirname = os.path.relpath(dirname, os.path.join('@out_folder@', pak_dir)) - filename = os.path.basename(resource_path) - dirname = os.path.join(out_path, dirname) - return (filename, dirname) - -def Unpack(pak_path, out_path): +def UnpackResource(root_dir, out_path, excludes, resource_path, resource_text): + dirname = os.path.dirname(resource_path) + # When files are generated, |dirname| becomes + # @out_folder@/<gen_path>/path_to_resource. To make the structure look as if + # this file was not generated, remove @out_folder@ and <gen_path>. + if ('@out_folder@' in dirname): + dirname = os.path.relpath(dirname, os.path.join('@out_folder@', root_dir)) + filename = os.path.basename(resource_path) + resource_path = os.path.join(dirname, filename).replace('\\', '/') + if (resource_path in excludes): + return + + out_dir = os.path.normpath( + os.path.join(out_path, dirname)).replace('\\', '/') + assert out_dir.startswith(out_path), \ + 'Cannot unpack files to locations not in %s. %s should be removed ' \ + 'from the pak file or excluded from unpack.' \ + % (out_path, resource_path) + + if not os.path.exists(out_dir): + os.makedirs(out_dir) + with open(os.path.join(out_dir, filename), 'w') as file: + file.write(resource_text) + +def Unpack(pak_path, out_path, pak_base_dir, excludes): pak_dir = os.path.dirname(pak_path) pak_id = os.path.splitext(os.path.basename(pak_path))[0] @@ -62,23 +75,25 @@ def Unpack(pak_path, out_path): resource_filenames[res.group(2)] = res.group(1) assert resource_filenames + root_dir = pak_base_dir if pak_base_dir else pak_dir # Extract packed files, while preserving directory structure. for (resource_id, text) in data.resources.iteritems(): - (filename, dirname) = GetFileAndDirName( - out_path, pak_dir, resource_filenames[resource_ids[resource_id]]) - if not os.path.exists(dirname): - os.makedirs(dirname) - with open(os.path.join(dirname, filename), 'w') as file: - file.write(text) - + UnpackResource(root_dir, out_path, excludes or [], + resource_filenames[resource_ids[resource_id]], text) def main(): parser = argparse.ArgumentParser() parser.add_argument('--pak_file') parser.add_argument('--out_folder') + # The expected reference point/root path for files appearing in the pak file. + # If this argument is not provided, the location of the pak file will be used + # by default. + parser.add_argument('--pak_base_dir') + # Resources in the pak file which should not be unpacked. + parser.add_argument('--excludes', nargs='*') args = parser.parse_args() - Unpack(args.pak_file, args.out_folder) + Unpack(args.pak_file, args.out_folder, args.pak_base_dir, args.excludes) timestamp_file_path = os.path.join(args.out_folder, _TIMESTAMP_FILENAME) with open(timestamp_file_path, 'a'): diff --git a/chromium/chrome/browser/resources/unpack_pak_test.py b/chromium/chrome/browser/resources/unpack_pak_test.py index 6572d9bc0d0..dd0ccb1dda5 100755 --- a/chromium/chrome/browser/resources/unpack_pak_test.py +++ b/chromium/chrome/browser/resources/unpack_pak_test.py @@ -4,10 +4,34 @@ # found in the LICENSE file. import unpack_pak +import tempfile +import os +import shutil import unittest +_HERE_DIR = os.path.dirname(__file__) class UnpackPakTest(unittest.TestCase): + def setUp(self): + self._out_folder = None + self._tmp_dirs = [] + + def tearDown(self): + for tmp_dir in self._tmp_dirs: + shutil.rmtree(tmp_dir) + + def _setup_output_dirs(self): + tmp_dir = tempfile.mkdtemp(dir=_HERE_DIR) + self._tmp_dirs.append(tmp_dir) + self._root_output_dir = os.path.join(tmp_dir, 'gen', 'mywebui') + os.makedirs(self._root_output_dir) + self._unpak_dir = os.path.normpath( + os.path.join(self._root_output_dir, 'unpak')).replace('\\', '/') + + def _read_unpacked_file(self, file_name): + assert self._unpak_dir + return open(os.path.join(self._unpak_dir, file_name), 'r').read() + def testMapFileLine(self): self.assertTrue(unpack_pak.ParseLine(' {"path.js", IDR_PATH}')) @@ -15,18 +39,35 @@ class UnpackPakTest(unittest.TestCase): self.assertTrue(unpack_pak.ParseLine(' {"path.js", IDR_PATH, false}')) self.assertTrue(unpack_pak.ParseLine(' {"path.js", IDR_PATH, true}')) - def testGetFileAndDirName(self): - (f, d) = unpack_pak.GetFileAndDirName( - 'out/build/gen/foo/foo.unpak', 'out/build/gen/foo', 'a/b.js') - self.assertEquals('b.js', f) - self.assertEquals('out/build/gen/foo/foo.unpak/a', d) - - def testGetFileAndDirNameForGeneratedResource(self): - (f, d) = unpack_pak.GetFileAndDirName( - 'out/build/gen/foo/foo.unpak', 'out/build/gen/foo', - '@out_folder@/out/build/gen/foo/a/b.js') - self.assertEquals('b.js', f) - self.assertEquals('out/build/gen/foo/foo.unpak/a', d) + def testUnpackResource(self): + self._setup_output_dirs() + unpack_pak.UnpackResource( + os.path.join('gen', 'mywebui'), self._unpak_dir, [], + 'sub_dir/some_element.js', 'alert(\'hello from element in sub_dir\');') + unpacked_contents = self._read_unpacked_file('sub_dir/some_element.js') + self.assertIn('hello from element in sub_dir', unpacked_contents) + + def testUnpackGeneratedResource(self): + self._setup_output_dirs() + generated_resource_path = os.path.join( + '@out_folder@', 'gen', 'mywebui', 'sub_dir', 'some_element.js') + unpack_pak.UnpackResource( + os.path.join('gen', 'mywebui'), self._unpak_dir, + [], generated_resource_path, + 'alert(\'hello from element in sub_dir\');') + unpacked_contents = self._read_unpacked_file('sub_dir/some_element.js') + self.assertIn('hello from element in sub_dir', unpacked_contents) + + def testUnpackExcludedResource(self): + self._setup_output_dirs() + generated_shared_resource_path = os.path.join( + '@out_folder@', 'gen', 'shared', 'shared_element.js') + self.assertEqual(0, len(os.listdir(self._root_output_dir))) + unpack_pak.UnpackResource( + os.path.join('gen', 'mywebui'), self._unpak_dir, + ['../shared/shared_element.js'], generated_shared_resource_path, + 'alert(\'hello from shared element\');') + self.assertEqual(0, len(os.listdir(self._root_output_dir))) if __name__ == '__main__': unittest.main() diff --git a/chromium/chrome/browser/resources/usb_internals/resources.grd b/chromium/chrome/browser/resources/usb_internals/resources.grd index 48bc89841bd..68f7a927a57 100644 --- a/chromium/chrome/browser/resources/usb_internals/resources.grd +++ b/chromium/chrome/browser/resources/usb_internals/resources.grd @@ -12,31 +12,25 @@ <includes> <include name="IDR_USB_INTERNALS_CSS" file="usb_internals.css" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_USB_INTERNALS_DESCRIPTOR_PANEL_JS" file="descriptor_panel.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_USB_INTERNALS_DEVICES_PAGE_JS" file="devices_page.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_USB_INTERNALS_HTML" file="usb_internals.html" flattenhtml="true" allowexternalscript="true" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_USB_INTERNALS_JS" file="usb_internals.js" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> <include name="IDR_USB_INTERNALS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\usb_internals\usb_internals.mojom-lite.js" use_base_dir="false" - type="BINDATA" - compress="gzip" /> + type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/user_manager/create_profile.js b/chromium/chrome/browser/resources/user_manager/create_profile.js index ca0c2d6858b..da2cff63f83 100644 --- a/chromium/chrome/browser/resources/user_manager/create_profile.js +++ b/chromium/chrome/browser/resources/user_manager/create_profile.js @@ -202,15 +202,7 @@ Polymer({ * @private */ i18nAllowIDAttr_(id) { - const opts = { - 'attrs': { - 'id'(node, value) { - return node.tagName == 'A'; - } - } - }; - - return this.i18nAdvanced(id, opts); + return this.i18nAdvanced(id, {attrs: ['id']}); }, /** diff --git a/chromium/chrome/browser/resources/web_app_internals/BUILD.gn b/chromium/chrome/browser/resources/web_app_internals/BUILD.gn new file mode 100644 index 00000000000..a02c5b41cf8 --- /dev/null +++ b/chromium/chrome/browser/resources/web_app_internals/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +html_to_js("components") { + js_files = [ "web_app_internals.js" ] +} + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ ":web_app_internals" ] +} + +js_library("web_app_internals") { + deps = [ + "//chrome/browser/ui/webui/internals/web_app:mojo_bindings_js_library_for_compile", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} diff --git a/chromium/chrome/browser/resources/web_app_internals/OWNERS b/chromium/chrome/browser/resources/web_app_internals/OWNERS new file mode 100644 index 00000000000..1255a2cc323 --- /dev/null +++ b/chromium/chrome/browser/resources/web_app_internals/OWNERS @@ -0,0 +1 @@ +file://chrome/browser/web_applications/OWNERS diff --git a/chromium/chrome/browser/resources/web_app_internals/index.html b/chromium/chrome/browser/resources/web_app_internals/index.html new file mode 100644 index 00000000000..9cbae310a6f --- /dev/null +++ b/chromium/chrome/browser/resources/web_app_internals/index.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> + <title>Web App Internals</title> + </head> + <body> + <web-app-internals></web-app-internals> + <script type="module" src="web_app_internals.js"></script> + </body> +</html> diff --git a/chromium/chrome/browser/resources/web_app_internals/web_app_internals.html b/chromium/chrome/browser/resources/web_app_internals/web_app_internals.html new file mode 100644 index 00000000000..2982293b591 --- /dev/null +++ b/chromium/chrome/browser/resources/web_app_internals/web_app_internals.html @@ -0,0 +1,76 @@ +<style> + h2 { + margin-bottom: 10px; + margin-top: 0; + } + + .section { + margin: 10px; + margin-bottom: 20px; + padding: 5px; + } + + .web-app { + background-color: var(--highlight, #00000007); + border-inline-start-color: rgb(0, 50, 220); + border-inline-start-style: solid; + } + + .highlight { + --highlight: #eff; + } + + .web-app-name { + font-weight: bold; + } +</style> + +<h1>Web App Internals</h1> + +<div class="section"> + BMO enabled: <b>[[isBmoEnabled_]]</b> + <template is="dom-if" if="[[!isBmoEnabled_]]"> + <p> + Web apps are using the extension system via bookmark apps, see + <a href="chrome://extensions-internals"> + chrome://extensions-internals + </a> + for bookmark app details. + </p> + <p> + Enable BMO via + <a href="chrome://flags/#enable-desktop-pwas-without-extensions"> + chrome://flags/#enable-desktop-pwas-without-extensions. + </a> + </p> + </template> +</div> + +<div class="section"> + <h2>Page index:</h2> + <template is="dom-repeat" items="[[webAppList_]]"> + <div> + <a href="#[[item.id]]"> + <img src="chrome://app-icon/[[item.id]]/32"> + [[item.name]] + </a> + </div> + </template> + <a href="#external">Externally installed web app prefs</a> +</div> + +<div class="section"> + <h2 id="details">Web apps details:</h2> + <template is="dom-repeat" items="[[webAppList_]]"> + <div class="section web-app" id="[[item.id]]"> + <h2>[[item.name]]</h2> + <img src="chrome://app-icon/[[item.id]]/128"> + <pre>[[item.debugInfo]]</pre> + </div> + </template> +</div> + +<div class="section" id="external"> + <h2>Externally installed web app prefs:</h2> + <pre>[[externallyInstalledWebAppPrefs_]]</pre> +</div> diff --git a/chromium/chrome/browser/resources/web_app_internals/web_app_internals.js b/chromium/chrome/browser/resources/web_app_internals/web_app_internals.js new file mode 100644 index 00000000000..dfc512aa1b6 --- /dev/null +++ b/chromium/chrome/browser/resources/web_app_internals/web_app_internals.js @@ -0,0 +1,88 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; +import './web_app_internals.mojom-lite.js'; +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +Polymer({ + is: 'web-app-internals', + + _template: html`{__html_template__}`, + + properties: { + /** + * Whether Bookmark apps off Extensions is enabled. + * @private {!boolean} + */ + isBmoEnabled_: Boolean, + + /** + * List of internal details about installed web apps. + * @private {!Array<!mojom.webAppInternals.WebApp>} + */ + webAppList_: Array, + + /** + * Prefs associated with non-user installed web apps. + * @private {!string} + */ + externallyInstalledWebAppPrefs_: String, + }, + + /** + * @override + * Fetches internal data about installed web apps from the browser. + */ + ready() { + (async () => { + const remote = + mojom.webAppInternals.WebAppInternalsPageHandler.getRemote(); + + this.isBmoEnabled_ = (await remote.isBmoEnabled()).isBmoEnabled; + + this.webAppList_ = (await remote.getWebApps()).webAppList; + this.webAppList_.sort((a, b) => a.name.localeCompare(b.name)); + + this.externallyInstalledWebAppPrefs_ = + (await remote.getExternallyInstalledWebAppPrefs()) + .externallyInstalledWebAppPrefs; + + this.highlightHashedId_(); + this.hashChangeListener_ = () => this.highlightHashedId_(); + window.addEventListener('hashchange', this.hashChangeListener_); + })(); + }, + + /** + * @override + * Cleans up global event listeners. + */ + detached() { + window.removeEventListener('hashchange', this.hashChangeListener_); + }, + + /** + * Reads the current URL hash, scrolls the targeted element into view and + * highlights it. + * @private + */ + highlightHashedId_() { + for (const element of this.shadowRoot.querySelectorAll('.highlight')) { + element.classList.remove('highlight'); + } + + if (!location.hash) { + return; + } + + const highlighted = this.shadowRoot.querySelector(location.hash); + if (!highlighted) { + return; + } + + highlighted.scrollIntoView(); + highlighted.classList.add('highlight'); + }, +}); diff --git a/chromium/chrome/browser/resources/webapks/webapks_ui_resources.grd b/chromium/chrome/browser/resources/webapks/webapks_ui_resources.grd index a744953fce7..e1bae8d7ae2 100644 --- a/chromium/chrome/browser/resources/webapks/webapks_ui_resources.grd +++ b/chromium/chrome/browser/resources/webapks/webapks_ui_resources.grd @@ -8,9 +8,9 @@ </outputs> <release seq="1"> <includes> - <include name="IDR_WEBAPKS_UI_CSS" file="about_webapks.css" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBAPKS_UI_HTML" file="about_webapks.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBAPKS_UI_JS" file="about_webapks.js" type="BINDATA" compress="gzip" /> + <include name="IDR_WEBAPKS_UI_CSS" file="about_webapks.css" type="BINDATA" /> + <include name="IDR_WEBAPKS_UI_HTML" file="about_webapks.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> + <include name="IDR_WEBAPKS_UI_JS" file="about_webapks.js" type="BINDATA" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/welcome/welcome_resources.grd b/chromium/chrome/browser/resources/welcome/welcome_resources.grd index 5a9e022c50c..64ba34f9eef 100644 --- a/chromium/chrome/browser/resources/welcome/welcome_resources.grd +++ b/chromium/chrome/browser/resources/welcome/welcome_resources.grd @@ -16,149 +16,127 @@ <includes> <include name="IDR_WELCOME_IMAGES_BACKGROUND_SVGS_BLUE_CIRCLE_SVG" file="images/background_svgs/blue_circle.svg" - compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_IMAGES_BACKGROUND_SVGS_GREEN_RECTANGLE_SVG" file="images/background_svgs/green_rectangle.svg" - compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_IMAGES_BACKGROUND_SVGS_GREY_OVAL_SVG" file="images/background_svgs/grey_oval.svg" - compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_IMAGES_BACKGROUND_SVGS_GREY_ROUNDED_RECTANGLE_SVG" file="images/background_svgs/grey_rounded_rectangle.svg" - compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_IMAGES_BACKGROUND_SVGS_RED_TRIANGLE_SVG" file="images/background_svgs/red_triangle.svg" - compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_IMAGES_BACKGROUND_SVGS_YELLOW_DOTS_SVG" file="images/background_svgs/yellow_dots.svg" - compress="gzip" type="BINDATA" /> <include name="IDR_WELCOME_IMAGES_BACKGROUND_SVGS_YELLOW_SEMICIRCLE_SVG" file="images/background_svgs/yellow_semicircle.svg" - compress="gzip" type="BINDATA" /> <!-- Generated Polymer 3 elements --> <include name="IDR_WELCOME_APP_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/welcome_app.js" - use_base_dir="false" type="BINDATA" compress="gzip" preprocess="true"/> + use_base_dir="false" type="BINDATA" preprocess="true"/> <include name="IDR_GOOGLE_APPS_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/google_apps/nux_google_apps.js" - use_base_dir="false" type="BINDATA" compress="gzip" preprocess="true"/> + use_base_dir="false" type="BINDATA" preprocess="true"/> <include name="IDR_SET_AS_DEFAULT_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/set_as_default/nux_set_as_default.js" - use_base_dir="false" type="BINDATA" compress="gzip" preprocess="true"/> + use_base_dir="false" type="BINDATA" preprocess="true"/> <include name="IDR_WELCOME_LANDING_VIEW_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/landing_view.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> <include name="IDR_WELCOME_SIGNIN_VIEW_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/signin_view.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> <include name="IDR_NTP_BACKGROUND_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/ntp_background/nux_ntp_background.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> <include name="IDR_WELCOME_SHARED_STEP_INDICATOR_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/shared/step_indicator.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> <include name="IDR_WELCOME_SHARED_ONBOARDING_BACKGROUND_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/shared/onboarding_background.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> <!-- Generated style files --> <include name="IDR_WELCOME_SHARED_ANIMATIONS_CSS_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/shared/animations_css.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> <include name="IDR_WELCOME_SHARED_CHOOSER_SHARED_CSS_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/shared/chooser_shared_css.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> <include name="IDR_WELCOME_SHARED_NAVI_COLORS_CSS_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/shared/navi_colors_css.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> <include name="IDR_WELCOME_SHARED_ACTION_LINK_STYLE_CSS_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/shared/action_link_style_css.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> <include name="IDR_WELCOME_SHARED_SPLASH_PAGES_SHARED_CSS_JS" file="${root_gen_dir}/chrome/browser/resources/welcome/shared/splash_pages_shared_css.js" - use_base_dir="false" type="BINDATA" compress="gzip"/> + use_base_dir="false" type="BINDATA"/> </includes> <structures> <structure name="IDR_WELCOME_LANDING_VIEW_PROXY_JS" file="landing_view_proxy.js" type="chrome_html" - compress="gzip" preprocess="true"/> <structure name="IDR_WELCOME_NAVIGATION_BEHAVIOR_JS" file="navigation_behavior.js" type="chrome_html" - compress="gzip" preprocess="true"/> <structure name="IDR_WELCOME_SHARED_BOOKMARK_PROXY_JS" file="shared/bookmark_proxy.js" - compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_SHARED_MODULE_METRICS_PROXY_JS" file="shared/module_metrics_proxy.js" - compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_SHARED_NUX_TYPES_JS" file="shared/nux_types.js" - compress="gzip" type="chrome_html" /> <structure name="IDR_WELCOME_SIGNIN_VIEW_PROXY_JS" file="signin_view_proxy.js" type="chrome_html" - compress="gzip" preprocess="true"/> <structure name="IDR_WELCOME_BROWSER_PROXY_JS" file="welcome_browser_proxy.js" - compress="gzip" type="chrome_html"/> <structure name="IDR_WELCOME_CSS" file="welcome.css" type="chrome_html" - compress="gzip" preprocess="true"/> <structure name="IDR_WELCOME_HTML" file="welcome.html" type="chrome_html" - compress="gzip" preprocess="true"/> <structure name="IDR_WELCOME_JS" file="welcome.js" type="chrome_html" - compress="gzip" preprocess="true"/> <!-- Google apps--> <structure name="IDR_GOOGLE_APP_PROXY_JS" file="google_apps/google_app_proxy.js" - compress="gzip" type="chrome_html" /> <structure name="IDR_GOOGLE_APPS_METRICS_PROXY_JS" file="google_apps/google_apps_metrics_proxy.js" - compress="gzip" type="chrome_html" /> <!-- Set as default--> <structure name="IDR_SET_AS_DEFAULT_PROXY_JS" file="set_as_default/nux_set_as_default_proxy.js" - compress="gzip" type="chrome_html" /> <!-- NTP background--> <structure name="IDR_NTP_BACKGROUND_PROXY_JS" file="ntp_background/ntp_background_proxy.js" - compress="gzip" type="chrome_html" /> <structure name="IDR_NTP_BACKGROUND_METRICS_PROXY_JS" file="ntp_background/ntp_background_metrics_proxy.js" - compress="gzip" type="chrome_html" /> </structures> </release> |