diff options
Diffstat (limited to 'chromium/chrome/browser/resources/md_extensions')
47 files changed, 2076 insertions, 496 deletions
diff --git a/chromium/chrome/browser/resources/md_extensions/BUILD.gn b/chromium/chrome/browser/resources/md_extensions/BUILD.gn new file mode 100644 index 00000000000..0d1cd29579f --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/BUILD.gn @@ -0,0 +1,43 @@ +import("../optimize_webui.gni") +import("//tools/grit/grit_rule.gni") +import("//chrome/common/features.gni") + +extensions_pak_file = "extensions_resources.pak" +unpak_folder = "extensions_resources.unpak" + +optimize_webui("build") { + host = "extensions" + html_in_files = [ "extensions.html" ] + html_out_files = [ "vulcanized.html" ] + input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir) + js_out_files = [ "crisper.js" ] + + deps = [ + ":unpak", + ] +} + +unpak("unpak") { + pak_file = extensions_pak_file + out_folder = unpak_folder + + deps = [ + ":flattened_resources", + ] +} + +grit("flattened_resources") { + source = "extensions_resources.grd" + + # The .grd contains references to generated files. + source_is_generated = true + + defines = chrome_grit_defines + outputs = [ + "grit/extensions_resources.h", + "grit/extensions_resources_map.cc", + "grit/extensions_resources_map.h", + extensions_pak_file, + ] + output_dir = "$root_gen_dir/chrome/browser/resources/md_extensions" +} diff --git a/chromium/chrome/browser/resources/md_extensions/code_section.html b/chromium/chrome/browser/resources/md_extensions/code_section.html index dff22ca8375..e0f7858f689 100644 --- a/chromium/chrome/browser/resources/md_extensions/code_section.html +++ b/chromium/chrome/browser/resources/md_extensions/code_section.html @@ -7,11 +7,22 @@ <dom-module id="extensions-code-section"> <template> <style include="cr-hidden-style"> - #main { + :host { + display: block; + } + + #scroll-container { border: 1px solid var(--paper-grey-500); + height: 100%; + overflow: auto; + position: relative; + } + + #main { color: var(--paper-grey-800); display: flex; font-family: monospace; + min-height: 100%; white-space: pre; } @@ -29,7 +40,7 @@ flex-direction: column; } - .highlight { + #highlight { background: var(--paper-red-100); } @@ -38,18 +49,20 @@ text-align: center; } </style> - <div id="main" hidden$="[[isEmpty(code)]]"> - <div id="line-numbers"> - <span>[[computeLineNumbersContent_(code.*)]]</span> - </div> - <div id="source"> - <span>[[code.beforeHighlight]]<!-- No whitespace allowed - --><span class="highlight" title="[[code.message]]"><!-- - -->[[code.highlight]]<!-- - --></span>[[code.afterHighlight]]</span> + <div id="scroll-container" hidden$="[[isEmpty(code)]]"> + <div id="main"> + <div id="line-numbers"> + <span>[[computeLineNumbersContent_(code.*)]]</span> + </div> + <div id="source"> + <span>[[code.beforeHighlight]]<!-- No whitespace allowed + --><span id="highlight" title="[[code.message]]"><!-- + -->[[code.highlight]]<!-- + --></span>[[code.afterHighlight]]</span> + </div> </div> </div> <div id="no-code" hidden$="[[!isEmpty(code)]]">[[couldNotDisplayCode]]</div> </template> - <script src="chrome://extensions/code_section.js"></script> + <script src="code_section.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/code_section.js b/chromium/chrome/browser/resources/md_extensions/code_section.js index 1ea32d783d0..d2fa2caab58 100644 --- a/chromium/chrome/browser/resources/md_extensions/code_section.js +++ b/chromium/chrome/browser/resources/md_extensions/code_section.js @@ -28,6 +28,10 @@ cr.define('extensions', function() { couldNotDisplayCode: String, }, + observers: [ + 'onHighlightChanged_(code.highlight)', + ], + /** * Returns true if no code could be displayed (e.g. because the file could * not be loaded). @@ -58,6 +62,15 @@ cr.define('extensions', function() { textContent += i + '\n'; return textContent; }, + + /** @private */ + onHighlightChanged_: function() { + // Smooth scroll the highlight to roughly the middle. + this.$['scroll-container'].scrollTo({ + top: this.$.highlight.offsetTop - this.clientHeight * 0.5, + behavior: 'smooth', + }); + }, }); return {CodeSection: CodeSection}; diff --git a/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp index 7dc433766ce..7689bd4eb76 100644 --- a/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp +++ b/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp @@ -14,6 +14,7 @@ { 'target_name': 'detail_view', 'dependencies': [ + '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', @@ -26,18 +27,28 @@ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, { + 'target_name': 'drag_and_drop_handler', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:drag_wrapper', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { 'target_name': 'drop_overlay', 'dependencies': [ - '<(DEPTH)/chrome/browser/resources/extensions/compiled_resources2.gyp:drag_and_drop_handler', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:drag_wrapper', + 'drag_and_drop_handler', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, { 'target_name': 'error_page', 'dependencies': [ + '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-menu/compiled_resources2.gyp:paper-menu-extracted', '<(EXTERNS_GYP):developer_private', @@ -72,10 +83,10 @@ { 'target_name': 'item_list', 'dependencies': [ + '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', - '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted', '<(EXTERNS_GYP):developer_private', 'item', ], @@ -95,6 +106,7 @@ { 'target_name': 'keyboard_shortcuts', 'dependencies': [ + '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(EXTERNS_GYP):developer_private', @@ -102,6 +114,22 @@ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, { + 'target_name': 'kiosk_browser_proxy', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'kiosk_dialog', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior', + 'kiosk_browser_proxy', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { 'target_name': 'load_error', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', @@ -124,6 +152,7 @@ 'item_util', 'load_error', 'keyboard_shortcuts', + 'kiosk_browser_proxy', 'navigation_helper', 'sidebar', 'toolbar', @@ -136,6 +165,7 @@ 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, @@ -152,7 +182,6 @@ { 'target_name': 'pack_dialog', 'dependencies': [ - '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(EXTERNS_GYP):developer_private', ], @@ -163,6 +192,7 @@ 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', '<(EXTERNS_GYP):developer_private', '<(EXTERNS_GYP):management', 'error_page', @@ -178,11 +208,19 @@ { 'target_name': 'shortcut_input', 'dependencies': [ - '<(DEPTH)/chrome/browser/resources/extensions/compiled_resources2.gyp:shortcut_util', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', - '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(EXTERNS_GYP):developer_private', + 'shortcut_util', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'shortcut_util', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, @@ -191,7 +229,6 @@ 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', - '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', 'navigation_helper', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], @@ -199,7 +236,6 @@ { 'target_name': 'toolbar', 'dependencies': [ - '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', ], diff --git a/chromium/chrome/browser/resources/md_extensions/detail_view.html b/chromium/chrome/browser/resources/md_extensions/detail_view.html index 3a23f8a31c0..c66a6a5eb6d 100644 --- a/chromium/chrome/browser/resources/md_extensions/detail_view.html +++ b/chromium/chrome/browser/resources/md_extensions/detail_view.html @@ -1,9 +1,11 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html"> -<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> -<link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_tooltip_icon.html"> <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/html/action_link_css.html"> @@ -13,18 +15,18 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> -<link rel="import" href="chrome://extensions/item_util.html"> -<link rel="import" href="chrome://extensions/navigation_helper.html"> +<link rel="import" href="strings.html"> +<link rel="import" href="item_util.html"> +<link rel="import" href="navigation_helper.html"> <dom-module id="extensions-detail-view"> <template> - <style include= - "iron-flex cr-hidden-style cr-icons action-link paper-toggle-style"> + <style include="iron-flex cr-shared-style cr-icons action-link + paper-button-style"> :host { --iron-icon-fill-color: var(--paper-grey-600); display: block; height: 100%; - overflow: auto; } #enable-section { @@ -35,6 +37,11 @@ -webkit-margin-end: 20px; } + #container { + height: 100%; + overflow: overlay; + } + #main { background-color: white; margin: auto; @@ -44,9 +51,7 @@ #top-bar { align-items: center; - color: var(--paper-grey-700); display: flex; - font-size: 14px; height: 40px; margin-bottom: 12px; padding: 8px 12px 0; @@ -61,6 +66,7 @@ #name { flex-grow: 1; + @apply(--cr-title-text); } .control-line { @@ -88,6 +94,11 @@ border-top: none; } + .section.continuation.warning { + padding-left: 21px; + padding-right: 8px; + } + .section:first-child { border: none; } @@ -111,146 +122,210 @@ width: auto; /* override the default button size of 24x24 */ } + .warning .action-button { + background: white; + color: var(--google-blue-500); + margin-left: 14px; + width: 78px; + } + + .warning div { + display: flex; + } + + .warning span { + color: var(--paper-red-700); + width: 484px; + } + + .warning-icon { + --iron-icon-fill-color: var(--paper-red-700); + --iron-icon-height: 19px; + --iron-icon-width: 19px; + margin-right: 16px; + } + ul { -webkit-padding-start: 20px; margin: 0; } + + #remove-extension { + width: 100%; + } </style> - <div id="main"> - <div id="top-bar"> - <button id="close-button" is="paper-icon-button-light" - class="icon-arrow-back no-overlap" - on-tap="onCloseButtonTap_"></button> - <img alt="" id="icon" src="[[data.iconUrl]]"> - <span id="name">[[data.name]]</span> - </div> - <div class="section continuation" id="enable-section"> - <div class="control-line"> - <span>[[computeEnabledText_(data.*)]]</span> - <div class="layout horizontal"> - <cr-tooltip-icon hidden$="[[!data.controlledInfo]]" - tooltip-text="[[data.controlledInfo.text]]" - icon-class="[[getIndicatorIcon_(data.controlledInfo.type)]]" - icon-aria-label="[[data.controlledInfo.type]]"> - </cr-tooltip-icon> - <paper-toggle-button id="enable-toggle" - checked="[[isEnabled_(data.state)]]" - on-change="onEnableChange_" - disabled="[[!isEnableToggleEnabled_(data.*)]]"> - </paper-toggle-button> + <div id="container"> + <div id="main"> + <div id="top-bar"> + <button id="close-button" is="paper-icon-button-light" + class="icon-arrow-back no-overlap" + on-tap="onCloseButtonTap_"></button> + <img alt="" id="icon" src="[[data.iconUrl]]"> + <span id="name">[[data.name]]</span> + </div> + <div class="section continuation" id="enable-section"> + <div class="control-line"> + <span>[[computeEnabledText_(data.*)]]</span> + <div class="layout horizontal"> + <cr-tooltip-icon hidden$="[[!data.controlledInfo]]" + tooltip-text="[[data.controlledInfo.text]]" + icon-class="[[getIndicatorIcon_(data.controlledInfo.type)]]" + icon-aria-label="[[data.controlledInfo.type]]"> + </cr-tooltip-icon> + <cr-toggle id="enable-toggle" + checked="[[isEnabled_(data.state)]]" + on-change="onEnableChange_" + disabled="[[!isEnableToggleEnabled_(data.*)]]"> + </cr-toggle> + </div> </div> </div> - </div> - <div class="section continuation block"> - <div class="section-title">$i18n{itemDescriptionLabel}</div> - <div class="section-content">[[data.description]]</div> - </div> - <div class="section block"> - <div class="section-title">$i18n{itemVersion}</div> - <div class="section-content">[[data.version]]</div> - </div> - <div class="section block" id="id-section" hidden$="[[!inDevMode]]"> - <div class="section-title">$i18n{itemIdHeading}</div> - <div class="section-content">[[data.id]]</div> - </div> - <div class="section" id="inspectable-views" hidden$="[[!inDevMode]]"> - <div class="section-title">$i18n{itemInspectViews}</div> - <div class="section-content"> - <ul id="inspect-views"> - <template is="dom-repeat" items="[[data.views]]"> - <li> - <a is="action-link" class="inspectable-view" - on-tap="onInspectTap_"> - [[computeInspectLabel_(item)]] - </a> - </li> - </template> - </ul> + <div id="warnings" hidden$="[[!hasWarnings_(data.*)]]"> + <div class="section continuation warning" id="suspicious-warning" + hidden$="[[!data.disableReasons.suspiciousInstall]]"> + <div> + <iron-icon class="warning-icon" icon="cr:warning"></iron-icon> + <span>$i18n{itemSuspiciousInstall}</span> + </div> + </div> + <div class="section continuation warning" id="corrupted-warning" + hidden$="[[!data.disableReasons.corruptInstall]]"> + <div> + <iron-icon class="warning-icon" icon="cr:warning"></iron-icon> + <span>$i18n{itemCorruptInstall}</span> + </div> + <paper-button id="repair-button" class="action-button" + on-tap="onRepairTap_"> + $i18n{itemRepair} + </paper-button> + </div> + <div class="section continuation warning" id="blacklisted-warning" + hidden$="[[!data.blacklistText]]"> + <div> + <iron-icon class="warning-icon" icon="cr:warning"></iron-icon> + <span>[[data.blacklistText]]</span> + </div> + </div> + <div class="section continuation warning" id="update-required-warning" + hidden$="[[!data.disableReasons.updateRequired]]"> + <div> + <iron-icon class="warning-icon" icon="cr:warning"></iron-icon> + <span>$i18n{updateRequiredByPolicy}</span> + </div> + </div> </div> - </div> - <div class="section block"> - <div class="section-title">$i18n{itemPermissions}</div> - <div class="section-content"> - <span id="no-permissions" - hidden$="[[hasPermissions_(data.permissions.splices)]]"> - $i18n{itemPermissionsEmpty} - </span> - <ul id="permissions-list" - hidden$="[[!hasPermissions_(data.permissions.splices)]]"> - <template is="dom-repeat" items="[[data.permissions]]"> - <li>[[item]]</li> - </template> - </ul> + <div class="section continuation block"> + <div class="section-title">$i18n{itemDescriptionLabel}</div> + <div class="section-content">[[data.description]]</div> </div> - </div> - <template is="dom-if" - if="[[hasDependentExtensions_(data.dependentExtensions.splices)]]"> <div class="section block"> - <div class="section-title">$i18n{itemDependencies}</div> + <div class="section-title">$i18n{itemVersion}</div> + <div class="section-content">[[data.version]]</div> + </div> + <div class="section block" id="id-section" hidden$="[[!inDevMode]]"> + <div class="section-title">$i18n{itemIdHeading}</div> + <div class="section-content">[[data.id]]</div> + </div> + <div class="section" id="inspectable-views" hidden$="[[!inDevMode]]"> + <div class="section-title">$i18n{itemInspectViews}</div> <div class="section-content"> - <ul id="dependent-extensions-list"> - <template is="dom-repeat" items="[[data.dependentExtensions]]"> - <li>[[computeDependentEntry_(item)]]</li> + <ul id="inspect-views"> + <template is="dom-repeat" items="[[data.views]]"> + <li> + <a is="action-link" class="inspectable-view" + on-tap="onInspectTap_"> + [[computeInspectLabel_(item)]] + </a> + </li> </template> </ul> </div> </div> - </template> - <template is="dom-if" if="[[shouldShowOptionsSection_(data.*)]]"> - <div class="section"> - <template is="dom-if" if="[[data.incognitoAccess.isEnabled]]"> - <div class="control-line"> - <span>$i18n{itemAllowIncognito}</span> - <paper-toggle-button id="allow-incognito" - checked="[[data.incognitoAccess.isActive]]" - on-change="onAllowIncognitoChange_"></paper-toggle-button> - </div> - </template> - <template is="dom-if" if="[[data.fileAccess.isEnabled]]"> - <div class="control-line"> - <span>$i18n{itemAllowOnFileUrls}</span> - <paper-toggle-button id="allow-on-file-urls" - checked="[[data.fileAccess.isActive]]" - on-change="onAllowOnFileUrlsChange_"></paper-toggle-button> - </div> - </template> - <template is="dom-if" if="[[data.runOnAllUrls.isEnabled]]"> - <div class="control-line"> - <span>$i18n{itemAllowOnAllSites}</span> - <paper-toggle-button id="allow-on-all-sites" - checked="[[data.runOnAllUrls.isActive]]" - on-change="onAllowOnAllSitesChange_"></paper-toggle-button> - </div> - </template> - <template is="dom-if" if="[[data.errorCollection.isEnabled]]"> - <div class="control-line"> - <span>$i18n{itemCollectErrors}</span> - <paper-toggle-button id="collect-errors" - checked="[[data.errorCollection.isActive]]" - on-change="onCollectErrorsChange_"></paper-toggle-button> - </div> - </template> + <div class="section block"> + <div class="section-title">$i18n{itemPermissions}</div> + <div class="section-content"> + <span id="no-permissions" + hidden$="[[hasPermissions_(data.permissions.splices)]]"> + $i18n{itemPermissionsEmpty} + </span> + <ul id="permissions-list" + hidden$="[[!hasPermissions_(data.permissions.splices)]]"> + <template is="dom-repeat" items="[[data.permissions]]"> + <li>[[item]]</li> + </template> + </ul> + </div> </div> - </template> - <div class="section" - hidden$="[[!shouldShowOptionsLink_(data.*)]]"> - <div class="control-line actionable" id="extensions-options" - on-tap="onOptionsTap_"> - <span>$i18n{itemOptions}</span> - <button class="icon-external" is="paper-icon-button-light"></button> + <template is="dom-if" + if="[[hasDependentExtensions_(data.dependentExtensions.splices)]]"> + <div class="section block"> + <div class="section-title">$i18n{itemDependencies}</div> + <div class="section-content"> + <ul id="dependent-extensions-list"> + <template is="dom-repeat" items="[[data.dependentExtensions]]"> + <li>[[computeDependentEntry_(item)]]</li> + </template> + </ul> + </div> + </div> + </template> + <template is="dom-if" if="[[shouldShowOptionsSection_(data.*)]]"> + <div class="section"> + <template is="dom-if" if="[[data.incognitoAccess.isEnabled]]"> + <div class="control-line"> + <span>$i18n{itemAllowIncognito}</span> + <cr-toggle id="allow-incognito" + checked="[[data.incognitoAccess.isActive]]" + on-change="onAllowIncognitoChange_"></cr-toggle> + </div> + </template> + <template is="dom-if" if="[[data.fileAccess.isEnabled]]"> + <div class="control-line"> + <span>$i18n{itemAllowOnFileUrls}</span> + <cr-toggle id="allow-on-file-urls" + checked="[[data.fileAccess.isActive]]" + on-change="onAllowOnFileUrlsChange_"></cr-toggle> + </div> + </template> + <template is="dom-if" if="[[data.runOnAllUrls.isEnabled]]"> + <div class="control-line"> + <span>$i18n{itemAllowOnAllSites}</span> + <cr-toggle id="allow-on-all-sites" + checked="[[data.runOnAllUrls.isActive]]" + on-change="onAllowOnAllSitesChange_"></cr-toggle> + </div> + </template> + <template is="dom-if" if="[[data.errorCollection.isEnabled]]"> + <div class="control-line"> + <span>$i18n{itemCollectErrors}</span> + <cr-toggle id="collect-errors" + checked="[[data.errorCollection.isActive]]" + on-change="onCollectErrorsChange_"></cr-toggle> + </div> + </template> + </div> + </template> + <div class="section" + hidden$="[[!shouldShowOptionsLink_(data.*)]]"> + <div class="control-line actionable" id="extensions-options" + on-tap="onOptionsTap_"> + <span>$i18n{itemOptions}</span> + <button class="icon-external" is="paper-icon-button-light"></button> + </div> </div> - </div> - <button is="cr-link-row" hidden="[[isControlled_(data.controlledInfo)]]" - icon-class="subpage-arrow" id="remove-extension" - label="$i18n{itemRemoveExtension}" on-tap="onRemoveTap_"> - </button> - <div class="section block"> - <div class="section-title">$i18n{itemSource}</div> - <div class="section-content"> - [[computeSourceString_(data.*)]] + <button class="hr" is="cr-link-row" + hidden="[[isControlled_(data.controlledInfo)]]" + icon-class="subpage-arrow" id="remove-extension" + label="$i18n{itemRemoveExtension}" on-tap="onRemoveTap_"> + </button> + <div class="section block"> + <div class="section-title">$i18n{itemSource}</div> + <div class="section-content"> + [[computeSourceString_(data.*)]] + </div> </div> </div> </div> </template> - <script src="chrome://extensions/detail_view.js"></script> + <script src="detail_view.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/detail_view.js b/chromium/chrome/browser/resources/md_extensions/detail_view.js index 0ea6870e448..9f7ab51e2db 100644 --- a/chromium/chrome/browser/resources/md_extensions/detail_view.js +++ b/chromium/chrome/browser/resources/md_extensions/detail_view.js @@ -8,7 +8,7 @@ cr.define('extensions', function() { const DetailView = Polymer({ is: 'extensions-detail-view', - behaviors: [I18nBehavior], + behaviors: [I18nBehavior, CrContainerShadowBehavior], properties: { /** @@ -71,6 +71,16 @@ cr.define('extensions', function() { }, /** + * @return {boolean} + * @private + */ + hasWarnings_: function() { + return this.data.disableReasons.corruptInstall || + this.data.disableReasons.suspiciousInstall || + this.data.disableReasons.updateRequired || !!this.data.blacklistText; + }, + + /** * @return {string} * @private */ @@ -143,6 +153,11 @@ cr.define('extensions', function() { }, /** @private */ + onRepairTap_: function() { + this.delegate.repairItem(this.data.id); + }, + + /** @private */ onAllowIncognitoChange_: function() { this.delegate.setItemAllowedIncognito( this.data.id, this.$$('#allow-incognito').checked); diff --git a/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.html b/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.html new file mode 100644 index 00000000000..2626f1e7a3f --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.html @@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="drag_and_drop_handler.js"></script> diff --git a/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.js b/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.js new file mode 100644 index 00000000000..f79bb43cde1 --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.js @@ -0,0 +1,96 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('extensions', function() { + 'use strict'; + + /** + * @param {boolean} dragEnabled + * @param {!EventTarget} target + * @constructor + * @implements cr.ui.DragWrapperDelegate + */ + function DragAndDropHandler(dragEnabled, target) { + this.dragEnabled = dragEnabled; + /** @private {!EventTarget} */ + this.eventTarget_ = target; + } + + // TODO(devlin): Un-chrome.send-ify this implementation. + DragAndDropHandler.prototype = { + /** @type {boolean} */ + dragEnabled: false, + + /** @override */ + shouldAcceptDrag: function(e) { + // External Extension installation can be disabled globally, e.g. while a + // different overlay is already showing. + if (!this.dragEnabled) + return false; + + // We can't access filenames during the 'dragenter' event, so we have to + // wait until 'drop' to decide whether to do something with the file or + // not. + // See: http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#concept-dnd-p + return !!e.dataTransfer.types && + e.dataTransfer.types.indexOf('Files') > -1; + }, + + /** @override */ + doDragEnter: function() { + chrome.send('startDrag'); + this.eventTarget_.dispatchEvent( + new CustomEvent('extension-drag-started')); + }, + + /** @override */ + doDragLeave: function() { + this.fireDragEnded_(); + chrome.send('stopDrag'); + }, + + /** @override */ + doDragOver: function(e) { + e.preventDefault(); + }, + + /** @override */ + doDrop: function(e) { + this.fireDragEnded_(); + if (e.dataTransfer.files.length != 1) + return; + + let toSend = ''; + // Files lack a check if they're a directory, but we can find out through + // its item entry. + for (let i = 0; i < e.dataTransfer.items.length; ++i) { + if (e.dataTransfer.items[i].kind == 'file' && + e.dataTransfer.items[i].webkitGetAsEntry().isDirectory) { + toSend = 'installDroppedDirectory'; + break; + } + } + // Only process files that look like extensions. Other files should + // navigate the browser normally. + if (!toSend && + /\.(crx|user\.js|zip)$/i.test(e.dataTransfer.files[0].name)) { + toSend = 'installDroppedFile'; + } + + if (toSend) { + e.preventDefault(); + chrome.send(toSend); + } + }, + + /** @private */ + fireDragEnded_: function() { + this.eventTarget_.dispatchEvent(new CustomEvent('extension-drag-ended')); + } + }; + + return { + DragAndDropHandler: DragAndDropHandler, + }; +}); diff --git a/chromium/chrome/browser/resources/md_extensions/drop_overlay.html b/chromium/chrome/browser/resources/md_extensions/drop_overlay.html index 5e22a036e60..7c6c510578f 100644 --- a/chromium/chrome/browser/resources/md_extensions/drop_overlay.html +++ b/chromium/chrome/browser/resources/md_extensions/drop_overlay.html @@ -3,10 +3,9 @@ <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/cr/ui/drag_wrapper.html"> -<link rel="import" href="chrome://resources/html/load_time_data.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> -<link rel="import" href="chrome://extensions/drag_and_drop_handler.html"> +<link rel="import" href="drag_and_drop_handler.html"> <dom-module id="extensions-drop-overlay"> <template> @@ -40,5 +39,5 @@ <div>$i18n{dropToInstall}</div> </div> </template> - <script src="chrome://extensions/drop_overlay.js"></script> + <script src="drop_overlay.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/error_page.html b/chromium/chrome/browser/resources/md_extensions/error_page.html index b3103aaa277..0ddb9486ee4 100644 --- a/chromium/chrome/browser/resources/md_extensions/error_page.html +++ b/chromium/chrome/browser/resources/md_extensions/error_page.html @@ -1,46 +1,75 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> -<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> -<link rel="import" href="chrome://extensions/code_section.html"> -<link rel="import" href="chrome://extensions/item_util.html"> -<link rel="import" href="chrome://extensions/navigation_helper.html"> +<link rel="import" href="code_section.html"> +<link rel="import" href="item_util.html"> +<link rel="import" href="navigation_helper.html"> <dom-module id="extensions-error-page"> <template> - <style include="cr-icons cr-hidden-style"> + <style include="paper-button-style cr-icons cr-shared-style"> + :host { + display: block; + height: 100%; + } + + #container { + height: 100%; + overflow: overlay; + } + #main { background-color: white; - height: 800px; - width: 90%; + margin: auto; + min-height: 100%; + width: 640px; + } + + .section { + padding: 0 var(--cr-section-padding); } #heading { - color: var(--paper-grey-600); height: 40px; margin-bottom: 30px; padding: 8px 12px 0; + @apply(--cr-title-text); } #errors-list { min-height: 100px; - padding: 0 10px; } .error-item { - align-items: center; - color: var(--paper-grey-800); - display: flex; - margin: 5px 0; + @apply(--cr-section); + padding-left: 0; + } + + .error-item button[is='paper-icon-button-light'] { + -webkit-margin-end: 0; } .error-item.selected { - background-color: #ccc; + background-color: rgba(0, 0, 0, 0.08); + } + + .error-item .start { + align-items: center; + align-self: stretch; /* Makes the tappable area fill its parent. */ + display: flex; + flex: 1; + padding: 0 var(--cr-section-padding); } .error-message { @@ -60,36 +89,128 @@ .icon-severity-fatal { content: url(error_severity_fatal.png); } + + #devtools-controls { + padding: 0 var(--cr-section-padding); + } + + #stack-trace-heading { + @apply(--cr-title-text); + align-items: center; + display: flex; + height: var(--cr-section-min-height); + } + + #stack-trace-container { + list-style: none; + margin-top: 0; + padding: 0; + } + + #stack-trace-container li { + cursor: pointer; + font-family: monospace; + padding: 4px; + } + + #stack-trace-container li.selected, + #stack-trace-container li:hover { + background: var(--google-blue-100); + } + + #dev-tool-button { + margin-bottom: 20px; + max-width: 300px; + } + + extensions-code-section { + background: white; + height: 200px; + } + + /* TODO(scottchen): extract to shared location from settings. */ + .separator { + -webkit-border-start: var(--cr-separator-line); + -webkit-margin-end: var(--cr-section-padding); + -webkit-margin-start: var(--cr-section-padding); + flex-shrink: 0; + --separator-gaps: 9px; + height: calc(var(--cr-section-min-height) - + var(--separator-gaps)); + + /** + * Makes the tappable area fill its parent. + * TODO(scottchen): This is an explicit reminder to override once + * .separator styling is extracted from settings. + */ + -webkit-margin-start: 0; + } + + /* TODO(scottchen): extract to shared location from settings. */ + .separator + button[is='paper-icon-button-light'] { + -webkit-margin-start: var(--cr-icon-ripple-margin); + } </style> - <div id="main"> - <div id="heading"> - <button id="close-button" is="paper-icon-button-light" - class="icon-arrow-back no-overlap" on-tap="onCloseButtonTap_"> - </button> - <span>$i18n{errorsPageHeading}</span> - </div> - <iron-list id="errors-list" items="[[calculateShownItems_(data.*)]]"> - <template> - <div class$="[[computeErrorClass_(selectedError_, item)]]" - error="[[item]]" - tabindex$="[[tabIndex]]" - on-tap="onErrorItemTap_" on-keydown="onErrorItemKeydown_"> - <img class$="[[computeErrorIconClass_(item)]]"> - <div class="error-message">[[item.message]]</div> - <button is="paper-icon-button-light" class="icon-delete-gray" - on-tap="onDeleteErrorTap_" tabindex$="[[tabIndex]]"></button> - </div> - </template> - </iron-list> - <div id="content-view"> - <extensions-code-section id="code-section" - could-not-display-code="$i18n{noErrorsToShow}"> - </extensions-code-section> - </div> - <div id="devtools-controls"> - <!--TODO--> + <div id="container"> + <div id="main"> + <div id="heading"> + <button id="close-button" is="paper-icon-button-light" + class="icon-arrow-back no-overlap" on-tap="onCloseButtonTap_"> + </button> + <span>$i18n{errorsPageHeading}</span> + </div> + <div class="section"> + <extensions-code-section id="code-section" + could-not-display-code="$i18n{noErrorsToShow}"> + </extensions-code-section> + <div id="errors-list"> + <template is="dom-repeat" items="[[calculateShownItems_(data.*)]]"> + <div class="item-container"> + <div class$="error-item [[computeErrorClass_(selectedError_, item)]]"> + <div class="start" on-tap="onErrorItemAction_" + on-keydown="onErrorItemAction_" tabindex="0"> + <img class$="[[computeErrorIconClass_(item)]]"> + <div class="error-message">[[item.message]]</div> + <cr-expand-button hidden="[[!computeIsRuntimeError_(item)]]" + expanded="[[isEqual_(selectedError_, item)]]" + tab-index="-1"> + </cr-expand-button> + </div> + <div class="separator"></div> + <button is="paper-icon-button-light" class="icon-delete-gray" + on-tap="onDeleteErrorAction_" + on-keydown="onDeleteErrorAction_"> + </button> + </div> + <template is="dom-if" if="[[computeIsRuntimeError_(item)]]"> + <iron-collapse opened="[[isEqual_(selectedError_, item)]]"> + <div id="devtools-controls"> + <div id="stack-trace-heading"> + $i18n{stackTrace} + </div> + <ul id="stack-trace-container"> + <template is="dom-repeat" items="[[item.stackTrace]]"> + <li on-tap="onStackFrameTap_" + hidden="[[!shouldDisplayFrame_(item.url)]]" + class$="[[getStackFrameClass_(item, selectedStackFrame_)]]"> + [[getStackTraceLabel_(item)]] + </li> + </template> + </ul> + <paper-button id="dev-tool-button" class="action-button" + disabled="[[!item.canInspect]]" + on-tap="onDevToolButtonTap_"> + $i18n{openInDevtool} + </paper-button> + </div> + </iron-collapse> + </template> + </div> + </template> + </iron-list> + </div> </div> </div> </template> - <script src="chrome://extensions/error_page.js"></script> + <script src="error_page.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/error_page.js b/chromium/chrome/browser/resources/md_extensions/error_page.js index 01bcf79e3cf..113561d6018 100644 --- a/chromium/chrome/browser/resources/md_extensions/error_page.js +++ b/chromium/chrome/browser/resources/md_extensions/error_page.js @@ -11,26 +11,43 @@ cr.define('extensions', function() { 'use strict'; /** @interface */ - const ErrorPageDelegate = function() {}; - - ErrorPageDelegate.prototype = { + class ErrorPageDelegate { /** * @param {string} extensionId - * @param {!Array<number>=} opt_errorIds - * @param {chrome.developerPrivate.ErrorType=} opt_type + * @param {!Array<number>=} errorIds + * @param {chrome.developerPrivate.ErrorType=} type */ - deleteErrors: assertNotReached, + deleteErrors(extensionId, errorIds, type) {} /** * @param {chrome.developerPrivate.RequestFileSourceProperties} args * @return {!Promise<!chrome.developerPrivate.RequestFileSourceResponse>} */ - requestFileSource: assertNotReached, - }; + requestFileSource(args) {} + + /** + * @param {!chrome.developerPrivate.OpenDevToolsProperties} args + */ + openDevTools(args) {} + } + + /** + * Get the URL relative to the main extension url. If the url is + * unassociated with the extension, this will be the full url. + * @param {string} url + * @param {?(ManifestError|RuntimeError)} error + * @return {string} + */ + function getRelativeUrl(url, error) { + const fullUrl = 'chrome-extension://' + error.extensionId + '/'; + return url.startsWith(fullUrl) ? url.substring(fullUrl.length) : url; + } const ErrorPage = Polymer({ is: 'extensions-error-page', + behaviors: [CrContainerShadowBehavior], + properties: { /** @type {!chrome.developerPrivate.ExtensionInfo|undefined} */ data: Object, @@ -40,6 +57,14 @@ cr.define('extensions', function() { /** @private {?(ManifestError|RuntimeError)} */ selectedError_: Object, + + /** @private {?chrome.developerPrivate.StackFrame}*/ + selectedStackFrame_: { + type: Object, + value: function() { + return null; + }, + }, }, observers: [ @@ -54,9 +79,8 @@ cr.define('extensions', function() { */ observeDataChanges_: function() { assert(this.data); - const e = this.data.manifestErrors[0] || this.data.runtimeErrors[0]; - if (e) - this.selectedError_ = e; + this.selectedError_ = + this.data.manifestErrors[0] || this.data.runtimeErrors[0] || null; }, /** @@ -98,14 +122,16 @@ cr.define('extensions', function() { }, /** - * @param {!Event} event + * @param {!Event} e * @private */ - onDeleteErrorTap_: function(event) { - // TODO(devlin): It would be cleaner if we could cast this to a - // PolymerDomRepeatEvent-type thing, but that doesn't exist yet. - const e = /** @type {!{model:Object}} */ (event); - this.delegate.deleteErrors(this.data.id, [e.model.item.id]); + onDeleteErrorAction_: function(e) { + if (e.type == 'keydown' && !((e.code == 'Space' || e.code == 'Enter'))) + return; + + this.delegate.deleteErrors( + this.data.id, [(/** @type {!{model:Object}} */ (e)).model.item.id]); + e.stopPropagation(); }, /** @@ -113,6 +139,11 @@ cr.define('extensions', function() { * @private */ onSelectedErrorChanged_: function() { + if (!this.selectedError_) { + this.$['code-section'].code = null; + return; + } + const error = this.selectedError_; const args = { extensionId: error.extensionId, @@ -130,6 +161,9 @@ cr.define('extensions', function() { args.lineNumber = error.stackTrace && error.stackTrace[0] ? error.stackTrace[0].lineNumber : 0; + this.selectedStackFrame_ = error.stackTrace && error.stackTrace[0] ? + error.stackTrace[0] : + null; break; } this.delegate.requestFileSource(args).then(code => { @@ -138,6 +172,100 @@ cr.define('extensions', function() { }, /** + * @return {boolean} + * @private + */ + computeIsRuntimeError_: function(item) { + return item.type == chrome.developerPrivate.ErrorType.RUNTIME; + }, + + /** + * The description is a human-readable summation of the frame, in the + * form "<relative_url>:<line_number> (function)", e.g. + * "myfile.js:25 (myFunction)". + * @param {!chrome.developerPrivate.StackFrame} frame + * @return {string} + * @private + */ + getStackTraceLabel_: function(frame) { + let description = getRelativeUrl(frame.url, this.selectedError_) + ':' + + frame.lineNumber; + + if (frame.functionName) { + const functionName = frame.functionName == '(anonymous function)' ? + loadTimeData.getString('anonymousFunction') : + frame.functionName; + description += ' (' + functionName + ')'; + } + + return description; + }, + + /** @private */ + getExpandedClass_: function() { + return this.stackTraceExpanded_ ? 'expanded' : ''; + }, + + /** + * @param {chrome.developerPrivate.StackFrame} frame + * @return {string} + * @private + */ + getStackFrameClass_: function(frame) { + return frame == this.selectedStackFrame_ ? 'selected' : ''; + }, + + /** + * This function is used to determine whether or not we want to show a + * stack frame. We don't want to show code from internal scripts. + * @param {string} url + * @return {boolean} + * @private + */ + shouldDisplayFrame_: function(url) { + // All our internal scripts are in the 'extensions::' namespace. + return !/^extensions::/.test(url); + }, + + /** + * @param {!Event} e + * @private + */ + onStackFrameTap_: function(e) { + const frame = (/** @type {!{model:Object}} */ (e)).model.item; + + this.selectedStackFrame_ = frame; + + this.delegate + .requestFileSource({ + extensionId: this.selectedError_.extensionId, + message: this.selectedError_.message, + pathSuffix: getRelativeUrl(frame.url, this.selectedError_), + lineNumber: frame.lineNumber, + }) + .then(code => { + this.$['code-section'].code = code; + }); + }, + + /** @private */ + onDevToolButtonTap_: function() { + // This guarantees renderProcessId and renderViewId. + assert( + this.selectedError_.type == + chrome.developerPrivate.ErrorType.RUNTIME); + assert(this.selectedStackFrame_); + + this.delegate.openDevTools({ + renderProcessId: this.selectedError_.renderProcessId, + renderViewId: this.selectedError_.renderViewId, + url: this.selectedStackFrame_.url, + lineNumber: this.selectedStackFrame_.lineNumber || 0, + columnNumber: this.selectedStackFrame_.columnNumber || 0, + }); + }, + + /** * Computes the class name for the error item depending on whether its * the currently selected error. * @param {!RuntimeError|!ManifestError} selectedError @@ -146,33 +274,37 @@ cr.define('extensions', function() { * @private */ computeErrorClass_: function(selectedError, error) { - return selectedError == error ? 'error-item selected' : 'error-item'; + return selectedError == error ? 'selected' : ''; }, /** - * Causes the given error to become the currently-selected error. - * @param {!RuntimeError|!ManifestError} error + * @param {!RuntimeError|!ManifestError} selected + * @param {!RuntimeError|!ManifestError} current + * @return {boolean} * @private */ - selectError_: function(error) { - this.selectedError_ = error; + isEqual_: function(selected, current) { + return selected == current; }, /** - * @param {!{model: !{item: (!RuntimeError|!ManifestError)}}} e + * Causes the given error to become the currently-selected error. + * @param {!RuntimeError|!ManifestError} error * @private */ - onErrorItemTap_: function(e) { - this.selectError_(e.model.item); + selectError_: function(error) { + this.selectedError_ = error; }, /** * @param {!{model: !{item: (!RuntimeError|!ManifestError)}}} e * @private */ - onErrorItemKeydown_: function(e) { - if (e.key == ' ' || e.key == 'Enter') - this.selectError_(e.model.item); + onErrorItemAction_: function(e) { + if (e.type == 'keydown' && !((e.code == 'Space' || e.code == 'Enter'))) + return; + + this.selectError_(e.model.item); }, }); diff --git a/chromium/chrome/browser/resources/md_extensions/extensions.html b/chromium/chrome/browser/resources/md_extensions/extensions.html index fb287b7b84f..1428eb4e94f 100644 --- a/chromium/chrome/browser/resources/md_extensions/extensions.html +++ b/chromium/chrome/browser/resources/md_extensions/extensions.html @@ -3,8 +3,11 @@ <head> <meta charset="utf8"> <title>$i18n{title}</title> +<if expr="not optimize_webui"> + <base href="chrome://extensions"> +</if> <link rel="import" href="chrome://resources/html/polymer.html"> - <link rel="import" href="chrome://extensions/manager.html"> + <link rel="import" href="manager.html"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <style> html { @@ -16,15 +19,15 @@ height: 100%; line-height: 154%; margin: 0; + overflow: hidden; + width: 100%; } </style> </head> <body> <extensions-manager></extensions-manager> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> - <link rel="import" href="chrome://resources/html/load_time_data.html"> - <link rel="import" href="chrome://extensions/strings.html"> - <link rel="import" href="chrome://extensions/service.html"> - <script src="chrome://extensions/extensions.js"></script> + <link rel="import" href="service.html"> + <script src="extensions.js"></script> </body> </html> diff --git a/chromium/chrome/browser/resources/md_extensions/extensions_resources.grd b/chromium/chrome/browser/resources/md_extensions/extensions_resources.grd new file mode 100644 index 00000000000..c8d179899b3 --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/extensions_resources.grd @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/extensions_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/extensions_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/extensions_resources_map.h" + type="resource_map_header" /> + <output filename="extensions_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <structures> + <structure name="IDR_MD_EXTENSIONS_EXTENSIONS_HTML" + file="extensions.html" + flattenhtml="true" + allowexternalscript="true" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_EXTENSIONS_JS" + file="extensions.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_CODE_SECTION_HTML" + file="code_section.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_CODE_SECTION_JS" + file="code_section.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_DETAIL_VIEW_HTML" + file="detail_view.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_DETAIL_VIEW_JS" + file="detail_view.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_DRAG_AND_DROP_HANDLER_HTML" + file="drag_and_drop_handler.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_DRAG_AND_DROP_HANDLER_JS" + file="drag_and_drop_handler.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_DROP_OVERLAY_HTML" + file="drop_overlay.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_DROP_OVERLAY_JS" + file="drop_overlay.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_ERROR_PAGE_HTML" + file="error_page.html" + flattenhtml="true" + allowexternalscript="true" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_ERROR_PAGE_JS" + file="error_page.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_KEYBOARD_SHORTCUTS_HTML" + file="keyboard_shortcuts.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_KEYBOARD_SHORTCUTS_JS" + file="keyboard_shortcuts.js" + type="chrome_html" /> + <if expr="chromeos"> + <structure name="IDR_MD_EXTENSIONS_KIOSK_BROWSER_PROXY_HTML" + file="kiosk_browser_proxy.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_KIOSK_BROWSER_PROXY_JS" + file="kiosk_browser_proxy.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_KIOSK_DIALOG_HTML" + file="kiosk_dialog.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_KIOSK_DIALOG_JS" + file="kiosk_dialog.js" + type="chrome_html" /> + </if> + <structure name="IDR_MD_EXTENSIONS_MANAGER_HTML" + file="manager.html" + type="chrome_html" + flattenhtml="true" + allowexternalscript="true" /> + <structure name="IDR_MD_EXTENSIONS_MANAGER_JS" + file="manager.js" + type="chrome_html" + flattenhtml="true" /> + <structure name="IDR_MD_EXTENSIONS_ICONS_HTML" + file="icons.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_ITEM_HTML" + file="item.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_ITEM_JS" + file="item.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_ITEM_LIST_HTML" + file="item_list.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_ITEM_LIST_JS" + file="item_list.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_ITEM_UTIL_HTML" + file="item_util.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_ITEM_UTIL_JS" + file="item_util.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_LOAD_ERROR_HTML" + file="load_error.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_LOAD_ERROR_JS" + file="load_error.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_NAVIGATION_HELPER_HTML" + file="navigation_helper.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_NAVIGATION_HELPER_JS" + file="navigation_helper.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_OPTIONS_DIALOG_HTML" + file="options_dialog.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_OPTIONS_DIALOG_JS" + file="options_dialog.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_HTML" + file="pack_dialog.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_JS" + file="pack_dialog.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_ALERT_HTML" + file="pack_dialog_alert.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_ALERT_JS" + file="pack_dialog_alert.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_SERVICE_HTML" + file="service.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_SERVICE_JS" + file="service.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_SHORTCUT_INPUT_HTML" + file="shortcut_input.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_SHORTCUT_INPUT_JS" + file="shortcut_input.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_SHORTCUT_UTIL_HTML" + file="shortcut_util.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_SHORTCUT_UTIL_JS" + file="shortcut_util.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_SIDEBAR_HTML" + file="sidebar.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_SIDEBAR_JS" + file="sidebar.js" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_TOOLBAR_HTML" + file="toolbar.html" + type="chrome_html" + flattenhtml="true" + allowexternalscript="true" /> + <structure name="IDR_MD_EXTENSIONS_TOOLBAR_JS" + file="toolbar.js" + type="chrome_html" + flattenhtml="true" /> + <structure name="IDR_MD_EXTENSIONS_STRINGS_HTML" + file="strings.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_VIEW_MANAGER_HTML" + file="view_manager.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_VIEW_MANAGER_JS" + file="view_manager.js" + type="chrome_html" /> + </structures> + </release> +</grit> diff --git a/chromium/chrome/browser/resources/md_extensions/extensions_resources_vulcanized.grd b/chromium/chrome/browser/resources/md_extensions/extensions_resources_vulcanized.grd new file mode 100644 index 00000000000..d3cb02311e7 --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/extensions_resources_vulcanized.grd @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/extensions_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/extensions_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/extensions_resources_map.h" + type="resource_map_header" /> + <output filename="extensions_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <include name="IDR_MD_EXTENSIONS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\md_extensions\vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> + <include name="IDR_MD_EXTENSIONS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\md_extensions\crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" /> + </includes> + </release> +</grit> diff --git a/chromium/chrome/browser/resources/md_extensions/item.html b/chromium/chrome/browser/resources/md_extensions/item.html index c396d2e4c95..2f35703d131 100644 --- a/chromium/chrome/browser/resources/md_extensions/item.html +++ b/chromium/chrome/browser/resources/md_extensions/item.html @@ -1,29 +1,28 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> -<link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.html"> <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/html/load_time_data.html"> -<link rel="import" href="chrome://extensions/icons.html"> -<link rel="import" href="chrome://extensions/item_util.html"> -<link rel="import" href="chrome://extensions/strings.html"> +<link rel="import" href="icons.html"> +<link rel="import" href="item_util.html"> +<link rel="import" href="strings.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/communication-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> -<link rel="import" href="chrome://extensions/navigation_helper.html"> +<link rel="import" href="navigation_helper.html"> <dom-module id="extensions-item"> <template> - <style include="iron-flex cr-hidden-style cr-icons action-link paper-button-style paper-toggle-style"> + <style include= + "iron-flex cr-hidden-style cr-icons action-link paper-button-style"> #icon-wrapper { align-self: flex-start; display: flex; @@ -41,21 +40,18 @@ display: flex; flex-direction: column; height: 160px; - width: 400px; + width: var(--extensions-card-width, 400px); } #card.dev-mode { height: 208px; } - #card.disabled { - opacity: 0.6; - } - #main { display: flex; flex-grow: 1; padding: 16px 20px 17px; + position: relative; } #content { @@ -135,26 +131,33 @@ color: white; display: none; margin-top: 8px; + max-width: 150px; opacity: 0.6; padding: 8px 12px; - position: absolute; transform: translateX(-50%); /* Move back 50% of width so that the text and icon share an x-center. */ } + :host-context([dir='rtl']) #source-indicator-text { + transform: translateX(50%); + } + #source-indicator:hover #source-indicator-text { display: block; } - paper-toggle-button { + cr-toggle { -webkit-margin-end: 8px; /* Avoid ripple from overlapping container. */ - cursor: pointer; } .action-button { color: var(--google-blue-500); } + #errors-button { + color: var(--google-red-700); + } + #dev-reload-button { -webkit-margin-end: 12px; } @@ -255,13 +258,13 @@ hidden$="[[!isTerminated_(data.state)]]"> $i18n{itemReload} </paper-button> - <paper-toggle-button id="enable-toggle" class="action-button" + <cr-toggle id="enable-toggle" class="action-button" checked="[[isEnabled_(data.state)]]" on-change="onEnableChange_" disabled="[[!isEnableToggleEnabled_(data.*)]]" hidden$="[[!showEnableToggle_(data.*)]]"> - </paper-toggle-button> + </cr-toggle> </div> </div> </template> - <script src="chrome://extensions/item.js"></script> + <script src="item.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/item.js b/chromium/chrome/browser/resources/md_extensions/item.js index eb7c4c4ebbf..f76a9fc0c95 100644 --- a/chromium/chrome/browser/resources/md_extensions/item.js +++ b/chromium/chrome/browser/resources/md_extensions/item.js @@ -4,57 +4,55 @@ cr.define('extensions', function() { /** @interface */ - const ItemDelegate = function() {}; - - ItemDelegate.prototype = { + class ItemDelegate { /** @param {string} id */ - deleteItem: assertNotReached, + deleteItem(id) {} /** * @param {string} id * @param {boolean} isEnabled */ - setItemEnabled: assertNotReached, + setItemEnabled(id, isEnabled) {} /** * @param {string} id * @param {boolean} isAllowedIncognito */ - setItemAllowedIncognito: assertNotReached, + setItemAllowedIncognito(id, isAllowedIncognito) {} /** * @param {string} id * @param {boolean} isAllowedOnFileUrls */ - setItemAllowedOnFileUrls: assertNotReached, + setItemAllowedOnFileUrls(id, isAllowedOnFileUrls) {} /** * @param {string} id * @param {boolean} isAllowedOnAllSites */ - setItemAllowedOnAllSites: assertNotReached, + setItemAllowedOnAllSites(id, isAllowedOnAllSites) {} /** * @param {string} id * @param {boolean} collectsErrors */ - setItemCollectsErrors: assertNotReached, + setItemCollectsErrors(id, collectsErrors) {} /** * @param {string} id * @param {chrome.developerPrivate.ExtensionView} view */ - inspectItemView: assertNotReached, + inspectItemView(id, view) {} /** @param {string} id */ - reloadItem: assertNotReached, + reloadItem(id) {} /** @param {string} id */ - repairItem: assertNotReached, + repairItem(id) {} /** @param {string} id */ - showItemOptionsPage: assertNotReached, - }; + showItemOptionsPage(id) {} + } const Item = Polymer({ is: 'extensions-item', @@ -100,7 +98,6 @@ cr.define('extensions', function() { assert(this.data); idElement.innerHTML = this.i18n('itemId', this.data.id); } - this.fire('extension-item-size-changed', {item: this.data}); }, /** @@ -282,11 +279,11 @@ cr.define('extensions', function() { */ computeDevReloadButtonHidden_: function() { // Only display the reload spinner if the extension is unpacked and - // not terminated (since if it's terminated, we'll show a crashed reload - // buton). + // enabled. There's no point in reloading a disabled extension, and we'll + // show a crashed reload buton if it's terminated. const showIcon = this.data.location == chrome.developerPrivate.Location.UNPACKED && - this.data.state != chrome.developerPrivate.ExtensionState.TERMINATED; + this.data.state == chrome.developerPrivate.ExtensionState.ENABLED; return !showIcon; }, diff --git a/chromium/chrome/browser/resources/md_extensions/item_list.html b/chromium/chrome/browser/resources/md_extensions/item_list.html index 78791afb6da..13b0c0bc166 100644 --- a/chromium/chrome/browser/resources/md_extensions/item_list.html +++ b/chromium/chrome/browser/resources/md_extensions/item_list.html @@ -1,21 +1,21 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-resizable-behavior/iron-resizable-behavior.html"> -<link rel="import" href="chrome://extensions/item.html"> +<link rel="import" href="item.html"> <dom-module id="extensions-item-list"> <template> - <style include="cr-hidden-style"> - :host { - @apply(--layout-vertical); + <style include="cr-shared-style"> + #items-container, + extensions-item { + --extensions-card-width: 400px; } - iron-list { - @apply(--layout-flex); - margin-top: 18px; + #container { + height: 100%; + overflow: overlay; } .empty-list-message { @@ -26,29 +26,45 @@ text-align: center; } - .wrapper { - padding: 6px; + #items-container { + --grid-gutter: 12px; + --max-columns: 3; + display: grid; + grid-column-gap: var(--grid-gutter); + grid-row-gap: var(--grid-gutter); + grid-template-columns: repeat(auto-fill, var(--extensions-card-width)); + justify-content: center; + margin: auto; + max-width: calc(var(--extensions-card-width) * var(--max-columns) + + var(--grid-gutter) * var(--max-columns)); + padding: calc(var(--grid-gutter) / 2); } - </style> - <div id="no-items" class="empty-list-message" - hidden$="[[!shouldShowEmptyItemsMessage_(items.length)]]"> - <span>$i18nRaw{noExtensionsOrApps}</span> - </div> - <div id="no-search-results" class="empty-list-message" - hidden$="[[!shouldShowEmptySearchMessage_(shownItems_.length)]]"> - <span>$i18n{noSearchResults}</span> - </div> - <iron-list id="list" items="[[shownItems_]]" - as="item" grid> - <template> - <div class="wrapper"> + extensions-item { + grid-column-start: auto; + grid-row-start: auto; + } + </style> + <div id="container"> + <div class="empty-list-message" hidden="[[!isGuest]]"> + $i18n{guestModeMessage} + </div> + <div id="no-items" class="empty-list-message" + hidden$="[[!shouldShowEmptyItemsMessage_(items.length)]]"> + <span>$i18nRaw{noExtensionsOrApps}</span> + </div> + <div id="no-search-results" class="empty-list-message" + hidden$="[[!shouldShowEmptySearchMessage_(shownItems_.length)]]"> + <span>$i18n{noSearchResults}</span> + </div> + <div id="items-container"> + <template is="dom-repeat" items="[[shownItems_]]"> <extensions-item data="[[item]]" delegate="[[delegate]]" - id="[[item.id]]" in-dev-mode="[[inDevMode]]"> + in-dev-mode="[[inDevMode]]"> </extensions-item> - </div> - </template> - </iron-list> + </template> + </div> + </div> </template> - <script src="chrome://extensions/item_list.js"></script> + <script src="item_list.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/item_list.js b/chromium/chrome/browser/resources/md_extensions/item_list.js index a2a38e15a04..e6cd997e5ea 100644 --- a/chromium/chrome/browser/resources/md_extensions/item_list.js +++ b/chromium/chrome/browser/resources/md_extensions/item_list.js @@ -6,7 +6,7 @@ cr.define('extensions', function() { const ItemList = Polymer({ is: 'extensions-item-list', - behaviors: [Polymer.IronResizableBehavior], + behaviors: [CrContainerShadowBehavior], properties: { /** @type {Array<!chrome.developerPrivate.ExtensionInfo>} */ @@ -20,6 +20,8 @@ cr.define('extensions', function() { value: false, }, + isGuest: Boolean, + filter: String, /** @private {Array<!chrome.developerPrivate.ExtensionInfo>} */ @@ -29,22 +31,6 @@ cr.define('extensions', function() { } }, - listeners: { - 'list.extension-item-size-changed': 'itemSizeChanged_', - 'view-enter-start': 'onViewEnterStart_', - }, - - /** - * Updates the size for a given item. - * @param {CustomEvent} e - * @private - * @suppress {checkTypes} Closure doesn't know $.list is an IronList. - */ - itemSizeChanged_: function(e) { - this.$.list.updateSizeForItem(e.detail.item); - this.fire('resize'); - }, - /** * Computes the list of items to be shown. * @param {Object} changeRecord The changeRecord for |items|. @@ -53,24 +39,21 @@ cr.define('extensions', function() { * @private */ computeShownItems_: function(changeRecord, filter) { - return this.items.filter(function(item) { - return item.name.toLowerCase().includes(this.filter.toLowerCase()); - }, this); + const formattedFilter = this.filter.trim().toLowerCase(); + return this.items.filter( + item => item.name.toLowerCase().includes(formattedFilter)); }, + /** @private */ shouldShowEmptyItemsMessage_: function() { - return this.items.length === 0; + return !this.isGuest && this.items.length === 0; }, + /** @private */ shouldShowEmptySearchMessage_: function() { - return !this.shouldShowEmptyItemsMessage_() && + return !this.isGuest && !this.shouldShowEmptyItemsMessage_() && this.shownItems_.length === 0; }, - - /** @private */ - onViewEnterStart_: function() { - this.fire('resize'); // This is needed to correctly render iron-list. - }, }); return { diff --git a/chromium/chrome/browser/resources/md_extensions/item_util.html b/chromium/chrome/browser/resources/md_extensions/item_util.html index 6429c3f459a..8836ce076d2 100644 --- a/chromium/chrome/browser/resources/md_extensions/item_util.html +++ b/chromium/chrome/browser/resources/md_extensions/item_util.html @@ -1,4 +1,4 @@ <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://resources/html/load_time_data.html"> -<script src="chrome://extensions/item_util.js"></script> +<link rel="import" href="strings.html"> +<script src="item_util.js"></script> diff --git a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.html b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.html index 1678a875485..ecde827f4f7 100644 --- a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.html +++ b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.html @@ -1,19 +1,31 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/md_select_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> -<link rel="import" href="chrome://extensions/shortcut_input.html"> +<link rel="import" href="shortcut_input.html"> <dom-module id="extensions-keyboard-shortcuts"> <template> - <style include="md-select cr-hidden-style"> + <style include="md-select cr-shared-style"> + :host { + height: 100%; + } + + #container { + height: 100%; + overflow: overlay; + padding-top: 24px; + } + .shortcut-card { + @apply(--cr-primary-text); @apply(--shadow-elevation-2dp); background-color: white; - color: var(--paper-grey-600); margin: 0 auto 16px auto; max-width: 928px; min-width: 600px; @@ -24,26 +36,35 @@ .command-entry { align-items: center; display: flex; - height: 48px; + height: var(--cr-section-min-height); } .command-name { - color: var(--paper-grey-900); flex: 1; } .command-entry .md-select-wrapper { - -webkit-margin-start: 40px; + -webkit-margin-start: var(--cr-section-padding); + } + + /* Vertically align with paper-input. */ + .command-entry .md-select { + /* TODO(scottchen): line-height needs adjustment to fix large fonts, + * same for paper-input. */ + line-height: 22px; + /* Below rules help align md-select and paper-input underline. */ + margin-top: 3px; + padding-bottom: 0; + padding-top: 0; } .card-title { align-items: center; - border-bottom: 1px solid var(--paper-grey-400); + border-bottom: var(--cr-separator-line); display: flex; - font-size: 14px; - font-weight: 500; margin-bottom: 9px; - padding: 16px 20px; + padding: 16px var(--cr-section-padding); + @apply(--cr-title-text); } .icon { @@ -58,12 +79,8 @@ -webkit-margin-end: 20px; -webkit-margin-start: 56px; } - - #main { - margin-top: 24px; - } </style> - <div id="main"> + <div id="container"> <template is="dom-repeat" items="[[calculateShownItems_(items.*)]]"> <div class="shortcut-card"> <div class="card-title"> @@ -101,5 +118,5 @@ </template> </div> </template> - <script src="chrome://extensions/keyboard_shortcuts.js"></script> + <script src="keyboard_shortcuts.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js index 160e3ce1097..e75b5cecdab 100644 --- a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js +++ b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js @@ -9,6 +9,8 @@ cr.define('extensions', function() { const KeyboardShortcuts = Polymer({ is: 'extensions-keyboard-shortcuts', + behaviors: [CrContainerShadowBehavior], + properties: { /** @type {Array<!chrome.developerPrivate.ExtensionInfo>} */ items: Array, diff --git a/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html b/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html new file mode 100644 index 00000000000..58f9bb8fe27 --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html @@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="kiosk_browser_proxy.js"></script> diff --git a/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js b/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js new file mode 100644 index 00000000000..91e7a70d4ca --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js @@ -0,0 +1,108 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview A helper object used from the "Kiosk" dialog to interact with + * the browser. + */ + +/** + * @typedef {{ + * kioskEnabled: boolean, + * autoLaunchEnabled: boolean + * }} + */ +let KioskSettings; + +/** + * @typedef {{ + * id: string, + * name: string, + * iconURL: string, + * autoLaunch: boolean, + * isLoading: boolean + * }} + */ +let KioskApp; + +/** + * @typedef {{ + * apps: !Array<!KioskApp>, + * disableBailout: boolean, + * hasAutoLaunchApp: boolean + * }} + */ +let KioskAppSettings; + +cr.define('extensions', function() { + + /** @interface */ + class KioskBrowserProxy { + /** @param {string} appId */ + addKioskApp(appId) {} + + /** @param {string} appId */ + disableKioskAutoLaunch(appId) {} + + /** @param {string} appId */ + enableKioskAutoLaunch(appId) {} + + /** @return {!Promise<!KioskAppSettings>} */ + getKioskAppSettings() {} + + /** @return {!Promise<!KioskSettings>} */ + initializeKioskAppSettings() {} + + /** @param {string} appId */ + removeKioskApp(appId) {} + + /** @param {boolean} disableBailout */ + setDisableBailoutShortcut(disableBailout) {} + } + + /** @implements {extensions.KioskBrowserProxy} */ + class KioskBrowserProxyImpl { + /** @override */ + initializeKioskAppSettings() { + return cr.sendWithPromise('initializeKioskAppSettings'); + } + + /** @override */ + getKioskAppSettings() { + return cr.sendWithPromise('getKioskAppSettings'); + } + + /** @override */ + addKioskApp(appId) { + chrome.send('addKioskApp', [appId]); + } + + /** @override */ + disableKioskAutoLaunch(appId) { + chrome.send('disableKioskAutoLaunch', [appId]); + } + + /** @override */ + enableKioskAutoLaunch(appId) { + chrome.send('enableKioskAutoLaunch', [appId]); + } + + /** @override */ + removeKioskApp(appId) { + chrome.send('removeKioskApp', [appId]); + } + + /** @override */ + setDisableBailoutShortcut(disableBailout) { + chrome.send('setDisableBailoutShortcut', [disableBailout]); + } + } + + cr.addSingletonGetter(KioskBrowserProxyImpl); + + return { + KioskBrowserProxy: KioskBrowserProxy, + KioskBrowserProxyImpl: KioskBrowserProxyImpl, + }; +}); diff --git a/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.html b/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.html new file mode 100644 index 00000000000..51100a4ec56 --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.html @@ -0,0 +1,144 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> +<link rel="import" href="chrome://resources/html/assert.html"> +<link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/html/util.html"> +<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> +<link rel="import" href="kiosk_browser_proxy.html"> + +<dom-module id="extensions-kiosk-dialog"> + <template> + <style include="cr-shared-style paper-button-style cr-icons"> + #add-kiosk-app { + --paper-input-container-input: { + font-size: inherit; + }; + align-items: center; + display: flex; + margin-bottom: 10px; + margin-top: 20px; + width: 350px; + } + + #add-kiosk-app paper-input { + flex: 1; + } + + #add-kiosk-app paper-button { + -webkit-margin-start: 10px; + } + + paper-button { + color: var(--google-blue-500); + } + + #kiosk-apps-list { + border: 1px solid var(--paper-grey-300); + padding: 10px; + } + + .list-item { + align-items: center; + border-bottom: 1px solid var(--paper-grey-300); + display: flex; + justify-content: space-between; + padding: 5px; + } + + .list-item:last-of-type { + border-bottom: none; + } + + .list-item:hover { + background-color: var(--paper-grey-300); + } + + .item-icon { + vertical-align: middle; + width: 25px; + } + + .item-controls { + visibility: hidden; + } + + .list-item:hover .item-controls { + visibility: visible; + } + </style> + <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}" + ignore-enter-key> + <div slot="title">$i18n{manageKioskApp}</div> + <div slot="body"> + <div id="kiosk-apps-list"> + <template is="dom-repeat" items="[[apps_]]"> + <div class="list-item"> + <div class="item-name"> + <img class="item-icon" src="[[item.iconURL]]"> + [[item.name]] + <span hidden="[[!item.autoLaunch]]"> + $i18n{kioskAutoLaunch} + </span> + </div> + <div class="item-controls"> + <paper-button hidden="[[!canEditAutoLaunch_]]" + on-tap="onAutoLaunchButtonTap_"> + [[getAutoLaunchButtonLabel_(item.autoLaunch, + '$i18nPolymer{kioskDisableAutoLaunch}', + '$i18nPolymer{kioskEnableAutoLaunch}')]] + </paper-button> + <button is="paper-icon-button-light" class="icon-delete-gray" + on-tap="onDeleteAppTap_"></button> + </div> + </div> + </template> + </div> + <div id="add-kiosk-app"> + <paper-input id="add-input" label="$i18n{kioskAddApp}" + placeholder="$i18n{kioskAddAppHint}" value="{{addAppInput_}}" + always-float-label invalid="[[errorAppId_]]" + error-message="[[getErrorMessage_( + '$i18nPolymer{kioskInvalidApp}', errorAppId_)]]" + on-keydown="clearInputInvalid_"> + </paper-input> + <paper-button id="add-button" on-tap="onAddAppTap_" + disabled="[[!addAppInput_]]"> + $i18n{add} + </paper-button> + </div> + <paper-checkbox disabled="[[!canEditBailout_]]" + on-pointerdown="onBailoutTap_" checked="[[bailoutDisabled_]]" + hidden="[[!canEditAutoLaunch_]]"> + $i18n{kioskDisableBailout} + </paper-checkbox> + </div> + <div slot="button-container"> + <paper-button class="action-button" on-tap="onDoneTap_"> + $i18n{done} + </paper-button> + </div> + </dialog> + <dialog is="cr-dialog" id="confirm-dialog" close-text="$i18n{close}" + ignore-enter-key on-close="stopPropagation_"> + <div slot="title">$i18n{kioskDisableBailoutWarningTitle}</div> + <div slot="body">$i18n{kioskDisableBailoutWarningBody}</div> + <div slot="button-container"> + <paper-button class="cancel-button" on-tap="onBailoutDialogCancelTap_"> + $i18n{cancel} + </paper-button> + <paper-button class="action-button" on-tap="onBailoutDialogConfirmTap_"> + $i18n{confirm} + </paper-button> + </div> + </dialog> + </template> + <script src="kiosk_dialog.js"></script> +</dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.js b/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.js new file mode 100644 index 00000000000..254c2c14d81 --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.js @@ -0,0 +1,185 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('extensions', function() { + 'use strict'; + + const KioskDialog = Polymer({ + is: 'extensions-kiosk-dialog', + behaviors: [WebUIListenerBehavior], + properties: { + /** @private {?string} */ + addAppInput_: { + type: String, + value: null, + }, + + /** @private {!Array<!KioskApp>} */ + apps_: Array, + + /** @private */ + bailoutDisabled_: Boolean, + + /** @private */ + canEditAutoLaunch_: Boolean, + + /** @private */ + canEditBailout_: Boolean, + + /** @private {?string} */ + errorAppId_: String, + }, + + /** @private {?extensions.KioskBrowserProxy} */ + kioskBrowserProxy_: null, + + /** @override */ + ready: function() { + this.kioskBrowserProxy_ = extensions.KioskBrowserProxyImpl.getInstance(); + }, + + /** @override */ + attached: function() { + this.kioskBrowserProxy_.initializeKioskAppSettings() + .then(params => { + this.canEditAutoLaunch_ = params.autoLaunchEnabled; + return this.kioskBrowserProxy_.getKioskAppSettings(); + }) + .then(this.setSettings_.bind(this)); + + this.addWebUIListener( + 'kiosk-app-settings-changed', this.setSettings_.bind(this)); + this.addWebUIListener('kiosk-app-updated', this.updateApp_.bind(this)); + this.addWebUIListener('kiosk-app-error', this.showError_.bind(this)); + + this.$.dialog.showModal(); + }, + + /** + * @param {!KioskAppSettings} settings + * @private + */ + setSettings_: function(settings) { + this.apps_ = settings.apps; + this.bailoutDisabled_ = settings.disableBailout; + this.canEditBailout_ = settings.hasAutoLaunchApp; + }, + + /** + * @param {!KioskApp} app + * @private + */ + updateApp_: function(app) { + const index = this.apps_.findIndex(a => a.id == app.id); + assert(index < this.apps_.length); + this.set('apps_.' + index, app); + }, + + /** + * @param {string} appId + * @private + */ + showError_: function(appId) { + this.errorAppId_ = appId; + }, + + /** + * @param {string} errorMessage + * @return {string} + * @private + */ + getErrorMessage_: function(errorMessage) { + return this.errorAppId_ + ' ' + errorMessage; + }, + + /** @private */ + onAddAppTap_: function() { + assert(this.addAppInput_); + this.kioskBrowserProxy_.addKioskApp(this.addAppInput_); + this.addAppInput_ = null; + }, + + /** @private */ + clearInputInvalid_: function() { + this.errorAppId_ = null; + }, + + /** + * @param {{model: {item: !KioskApp}}} event + * @private + */ + onAutoLaunchButtonTap_: function(event) { + const app = event.model.item; + if (app.autoLaunch) { // If the app is originally set to + // auto-launch. + this.kioskBrowserProxy_.disableKioskAutoLaunch(app.id); + } else { + this.kioskBrowserProxy_.enableKioskAutoLaunch(app.id); + } + }, + + /** + * @param {!Event} event + * @private + */ + onBailoutTap_: function(event) { + event.preventDefault(); + if (this.bailoutDisabled_) { + this.kioskBrowserProxy_.setDisableBailoutShortcut(false); + this.bailoutDisabled_ = false; + this.$['confirm-dialog'].close(); + } else { + this.$['confirm-dialog'].showModal(); + } + }, + + /** @private */ + onBailoutDialogCancelTap_: function() { + this.$['confirm-dialog'].cancel(); + }, + + /** @private */ + onBailoutDialogConfirmTap_: function() { + this.kioskBrowserProxy_.setDisableBailoutShortcut(true); + this.bailoutDisabled_ = true; + this.$['confirm-dialog'].close(); + }, + + /** @private */ + onDoneTap_: function() { + this.$.dialog.close(); + }, + + /** + * @param {{model: {item: !KioskApp}}} event + * @private + */ + onDeleteAppTap_: function(event) { + this.kioskBrowserProxy_.removeKioskApp(event.model.item.id); + }, + + /** + * @param {boolean} autoLaunched + * @param {string} disableStr + * @param {string} enableStr + * @return {string} + * @private + */ + getAutoLaunchButtonLabel_: function(autoLaunched, disableStr, enableStr) { + return autoLaunched ? disableStr : enableStr; + }, + + /** + * @param {!Event} e + * @private + */ + stopPropagation_: function(e) { + e.stopPropagation(); + }, + }); + + return { + KioskDialog: KioskDialog, + }; +}); diff --git a/chromium/chrome/browser/resources/md_extensions/load_error.html b/chromium/chrome/browser/resources/md_extensions/load_error.html index 1f3212d870a..0d0f1237a5c 100644 --- a/chromium/chrome/browser/resources/md_extensions/load_error.html +++ b/chromium/chrome/browser/resources/md_extensions/load_error.html @@ -6,7 +6,7 @@ <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://extensions/code_section.html"> +<link rel="import" href="code_section.html"> <dom-module id="extensions-load-error"> <template> @@ -47,5 +47,5 @@ </div> </dialog> </template> - <script src="chrome://extensions/load_error.js"></script> + <script src="load_error.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/load_error.js b/chromium/chrome/browser/resources/md_extensions/load_error.js index 5d1cc8e98dc..67391a189ff 100644 --- a/chromium/chrome/browser/resources/md_extensions/load_error.js +++ b/chromium/chrome/browser/resources/md_extensions/load_error.js @@ -6,15 +6,13 @@ cr.define('extensions', function() { 'use strict'; /** @interface */ - function LoadErrorDelegate() {} - - LoadErrorDelegate.prototype = { + class LoadErrorDelegate { /** * Attempts to load the previously-attempted unpacked extension. * @param {string} retryId */ - retryLoadUnpacked: assertNotReached, - }; + retryLoadUnpacked(retryId) {} + } const LoadError = Polymer({ is: 'extensions-load-error', diff --git a/chromium/chrome/browser/resources/md_extensions/manager.html b/chromium/chrome/browser/resources/md_extensions/manager.html index 6b401d1dafc..c38263894b1 100644 --- a/chromium/chrome/browser/resources/md_extensions/manager.html +++ b/chromium/chrome/browser/resources/md_extensions/manager.html @@ -7,44 +7,43 @@ <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/promise_resolver.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> -<link rel="import" href="chrome://extensions/detail_view.html"> -<link rel="import" href="chrome://extensions/drop_overlay.html"> -<link rel="import" href="chrome://extensions/error_page.html"> -<link rel="import" href="chrome://extensions/item_list.html"> -<link rel="import" href="chrome://extensions/item_util.html"> -<link rel="import" href="chrome://extensions/keyboard_shortcuts.html"> -<link rel="import" href="chrome://extensions/load_error.html"> -<link rel="import" href="chrome://extensions/navigation_helper.html"> -<link rel="import" href="chrome://extensions/options_dialog.html"> -<link rel="import" href="chrome://extensions/pack_dialog.html"> -<link rel="import" href="chrome://extensions/service.html"> -<link rel="import" href="chrome://extensions/sidebar.html"> -<link rel="import" href="chrome://extensions/toolbar.html"> -<link rel="import" href="chrome://extensions/view_manager.html"> +<link rel="import" href="detail_view.html"> +<link rel="import" href="drop_overlay.html"> +<link rel="import" href="error_page.html"> +<link rel="import" href="item_list.html"> +<link rel="import" href="item_util.html"> +<link rel="import" href="keyboard_shortcuts.html"> +<link rel="import" href="load_error.html"> +<link rel="import" href="navigation_helper.html"> +<link rel="import" href="options_dialog.html"> +<link rel="import" href="pack_dialog.html"> +<link rel="import" href="service.html"> +<link rel="import" href="sidebar.html"> +<link rel="import" href="toolbar.html"> +<link rel="import" href="view_manager.html"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> +<if expr="chromeos"> +<link rel="import" href="kiosk_browser_proxy.html"> +<link rel="import" href="kiosk_dialog.html"> +</if> + <dom-module id="extensions-manager"> <template> <style include="cr-hidden-style"> :host { + display: flex; + flex-direction: column; height: 100%; } - #panel { - --paper-header-panel-standard-container: { - display: flex; - }; - } - extensions-sidebar { flex-basis: 256px; } #viewManager { - flex-grow: 1; - overflow-y: auto; + flex: 1; + position: relative; } extensions-item { @@ -56,41 +55,52 @@ } </style> <extensions-drop-overlay></extensions-drop-overlay> - <paper-header-panel id="panel"> - <extensions-toolbar class="paper-header" in-dev-mode="[[inDevMode]]" - on-pack-tap="onPackTap_" delegate="[[delegate]]" - on-cr-toolbar-menu-tap="onMenuButtonTap_" - on-search-changed="onFilterChanged_"> - </extensions-toolbar> - <dialog id="drawer" is="cr-drawer" heading="$i18n{toolbarTitle}"> - <div class="drawer-content"> - <extensions-sidebar id="sidebar"></extensions-sidebar> - </div> - </dialog> - <extensions-view-manager id="viewManager"> - <extensions-item-list id="items-list" - items="[[itemsList_]]" - delegate="[[delegate]]" in-dev-mode="[[inDevMode]]" - filter="[[filter]]" hidden$="[[!didInitPage_]]" slot="view"> - </extensions-item-list> - <extensions-detail-view id="details-view" delegate="[[delegate]]" - in-dev-mode="[[inDevMode]]" data="[[detailViewItem_]]" - slot="view"> - </extensions-detail-view> - <extensions-keyboard-shortcuts id="keyboard-shortcuts" - items="[[extensions]]" slot="view"> - </extensions-keyboard-shortcuts> - <extensions-error-page id="error-page" - data="[[errorPageItem_]]" delegate="[[delegate]]" slot="view"> - </extensions-error-page> - </extensions-view-manager> - <extensions-options-dialog id="options-dialog"> - </extensions-options-dialog> - <extensions-pack-dialog id="pack-dialog" delegate="[[delegate]]"> - </extensions-pack-dialog> - <extensions-load-error id="load-error" delegate="[[delegate]]"> - </extensions-load-error> - </paper-header-panel> + <extensions-toolbar is-guest="[[isGuest_]]" in-dev-mode="[[inDevMode]]" + on-pack-tap="onPackTap_" delegate="[[delegate]]" + on-cr-toolbar-menu-tap="onMenuButtonTap_" + on-search-changed="onFilterChanged_" +<if expr="chromeos"> + on-kiosk-tap="onKioskTap_" + kiosk-enabled="[[kioskEnabled_]]" +</if> + > + </extensions-toolbar> + <dialog id="drawer" is="cr-drawer" heading="$i18n{toolbarTitle}" + align="$i18n{textdirection}"> + <div class="drawer-content"> + <extensions-sidebar id="sidebar"></extensions-sidebar> + </div> + </dialog> + <extensions-view-manager id="viewManager" role="main"> + <extensions-item-list id="items-list" items="[[itemsList_]]" + delegate="[[delegate]]" in-dev-mode="[[inDevMode]]" + filter="[[filter]]" hidden$="[[!didInitPage_]]" slot="view" + is-guest="[[isGuest_]]"> + </extensions-item-list> + <extensions-detail-view id="details-view" delegate="[[delegate]]" + in-dev-mode="[[inDevMode]]" data="[[detailViewItem_]]" + slot="view"> + </extensions-detail-view> + <extensions-keyboard-shortcuts id="keyboard-shortcuts" + items="[[extensions]]" slot="view"> + </extensions-keyboard-shortcuts> + <extensions-error-page id="error-page" + data="[[errorPageItem_]]" delegate="[[delegate]]" slot="view"> + </extensions-error-page> + </extensions-view-manager> + <extensions-options-dialog id="options-dialog"> + </extensions-options-dialog> + <extensions-pack-dialog id="pack-dialog" delegate="[[delegate]]"> + </extensions-pack-dialog> + <extensions-load-error id="load-error" delegate="[[delegate]]"> + </extensions-load-error> +<if expr="chromeos"> + <template is="dom-if" if="[[showKioskDialog_]]" restamp> + <extensions-kiosk-dialog id="kiosk-dialog" + on-close="onKioskDialogClose_"> + </extensions-kiosk-dialog> + </template> +</if> </template> - <script src="chrome://extensions/manager.js"></script> -</dom-module>
\ No newline at end of file + <script src="manager.js"></script> +</dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/manager.js b/chromium/chrome/browser/resources/md_extensions/manager.js index 9ac31f6fd5a..eb197cabeb3 100644 --- a/chromium/chrome/browser/resources/md_extensions/manager.js +++ b/chromium/chrome/browser/resources/md_extensions/manager.js @@ -35,9 +35,6 @@ cr.define('extensions', function() { behaviors: [I18nBehavior], properties: { - /** @type {extensions.Sidebar} */ - sidebar: Object, - /** @type {extensions.Toolbar} */ toolbar: Object, @@ -45,6 +42,13 @@ cr.define('extensions', function() { // passed to different elements as different types. delegate: Object, + isGuest_: { + type: Boolean, + value: function() { + return loadTimeData.getBoolean('isGuest'); + }, + }, + inDevMode: { type: Boolean, value: false, @@ -104,6 +108,20 @@ cr.define('extensions', function() { type: Boolean, value: false, }, + + // <if expr="chromeos"> + /** @private */ + kioskEnabled_: { + type: Boolean, + value: false, + }, + + /** @private */ + showKioskDialog_: { + type: Boolean, + value: false, + }, + // </if> }, /** @@ -113,19 +131,46 @@ cr.define('extensions', function() { */ currentPage_: null, + /** + * The ID of the listner on |extensions.navigation|. Stored so that the + * listener can be removed when this element is detached (happens in tests). + * @private {?number} + */ + navigationListener_: null, + + /** @override */ created: function() { this.readyPromiseResolver = new PromiseResolver(); }, + /** @override */ ready: function() { this.toolbar = /** @type {extensions.Toolbar} */ (this.$$('extensions-toolbar')); this.readyPromiseResolver.resolve(); - extensions.navigation.onRouteChanged(newPage => { + + // <if expr="chromeos"> + extensions.KioskBrowserProxyImpl.getInstance() + .initializeKioskAppSettings() + .then(params => { + this.kioskEnabled_ = params.kioskEnabled; + }); + // </if> + }, + + /** @override */ + attached: function() { + this.navigationListener_ = extensions.navigation.addListener(newPage => { this.changePage_(newPage); }); }, + /** @override */ + detached: function() { + assert(extensions.navigation.removeListener(this.navigationListener_)); + this.navigationListener_ = null; + }, + get keyboardShortcuts() { return this.$['keyboard-shortcuts']; }, @@ -165,7 +210,19 @@ cr.define('extensions', function() { /** @private */ onMenuButtonTap_: function() { - this.$.drawer.toggle(); + this.$.drawer.openDrawer(); + + // Sidebar needs manager to inform it of what to highlight since it + // has no access to item-specific page. + let page = extensions.navigation.getCurrentPage(); + if (page.extensionId) { + // Find out what type of item we're looking at, and replace page info + // with that list type. + const data = assert(this.getData_(page.extensionId)); + page = {page: Page.LIST, type: extensions.getItemListType(data)}; + } + + this.$.sidebar.updateSelected(page); }, /** @@ -288,7 +345,7 @@ cr.define('extensions', function() { */ changePage_: function(newPage) { this.$.drawer.closeDrawer(); - if (this.optionsDialog.open) + if (this.optionsDialog && this.optionsDialog.open) this.optionsDialog.close(); const fromPage = this.currentPage_ ? this.currentPage_.page : null; @@ -298,7 +355,7 @@ cr.define('extensions', function() { data = assert(this.getData_(newPage.extensionId)); if (newPage.hasOwnProperty('type')) - this.listType_ = newPage.type; + this.listType_ = /** @type {extensions.ShowingType} */ (newPage.type); if (toPage == Page.DETAILS) this.detailViewItem_ = assert(data); @@ -327,6 +384,17 @@ cr.define('extensions', function() { this.$['pack-dialog'].show(); }, + // <if expr="chromeos"> + /** @private */ + onKioskTap_: function() { + this.showKioskDialog_ = true; + }, + + onKioskDialogClose_: function() { + this.showKioskDialog_ = false; + }, + // </if> + /** * @param {!extensions.ShowingType} listType * @private diff --git a/chromium/chrome/browser/resources/md_extensions/navigation_helper.html b/chromium/chrome/browser/resources/md_extensions/navigation_helper.html index 15666da1184..2521c5d5f3f 100644 --- a/chromium/chrome/browser/resources/md_extensions/navigation_helper.html +++ b/chromium/chrome/browser/resources/md_extensions/navigation_helper.html @@ -1,3 +1,4 @@ <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> -<script src="chrome://extensions/navigation_helper.js"></script> +<link rel="import" href="strings.html"> +<script src="navigation_helper.js"></script> diff --git a/chromium/chrome/browser/resources/md_extensions/navigation_helper.js b/chromium/chrome/browser/resources/md_extensions/navigation_helper.js index 768b9f1aef0..9437730ea02 100644 --- a/chromium/chrome/browser/resources/md_extensions/navigation_helper.js +++ b/chromium/chrome/browser/resources/md_extensions/navigation_helper.js @@ -29,27 +29,52 @@ extensions.ShowingType = { /** @typedef {{page: Page, extensionId: (string|undefined), - subpage: (!Dialog|undefined)}} */ + subpage: (!Dialog|undefined), + type: (!extensions.ShowingType|undefined)}} */ let PageState; cr.define('extensions', function() { 'use strict'; /** + * Regular expression that captures the leading slash, the content and the + * trailing slash in three different groups. + * @const {!RegExp} + */ + const CANONICAL_PATH_REGEX = /(^\/)([\/-\w]+)(\/$)/; + + /** * A helper object to manage in-page navigations. Since the extensions page * needs to support different urls for different subpages (like the details * page), we use this object to manage the history and url conversions. */ class NavigationHelper { constructor() { - /** @private {!Array<function(!PageState)>} */ - this.listeners_ = []; + // Redirect if route not supported. + let validPathnames = ['/']; + if (!loadTimeData.getBoolean('isGuest')) { + validPathnames.push('/shortcuts', '/apps'); + } + if (!validPathnames.includes(this.currentPath_)) { + window.history.replaceState(undefined, '', '/'); + } + + /** @private {number} */ + this.nextListenerId_ = 1; + + /** @private {!Map<number, function(!PageState)>} */ + this.listeners_ = new Map(); window.addEventListener('popstate', () => { this.notifyRouteChanged_(this.getCurrentPage()); }); } + /** @private */ + get currentPath_() { + return location.pathname.replace(CANONICAL_PATH_REGEX, '$1$2'); + } + /** * @return {!PageState} The page that should be displayed for the current * URL. @@ -66,10 +91,10 @@ cr.define('extensions', function() { if (id) return {page: Page.ERRORS, extensionId: id}; - if (location.pathname == '/shortcuts') + if (this.currentPath_ == '/shortcuts') return {page: Page.SHORTCUTS}; - if (location.pathname == '/apps') + if (this.currentPath_ == '/apps') return {page: Page.LIST, type: extensions.ShowingType.APPS}; return {page: Page.LIST, type: extensions.ShowingType.EXTENSIONS}; @@ -78,9 +103,22 @@ cr.define('extensions', function() { /** * Function to add subscribers. * @param {!function(!PageState)} listener + * @return {number} A numerical ID to be used for removing the listener. */ - onRouteChanged(listener) { - this.listeners_.push(listener); + addListener(listener) { + const nextListenerId = this.nextListenerId_++; + this.listeners_.set(nextListenerId, listener); + return nextListenerId; + } + + /** + * Remove a previously registered listener. + * @param {number} id + * @return {boolean} Whether a listener with the given ID was actually found + * and removed. + */ + removeListener(id) { + return this.listeners_.delete(id); } /** @@ -88,9 +126,9 @@ cr.define('extensions', function() { * @private */ notifyRouteChanged_(newPage) { - for (const listener of this.listeners_) { + this.listeners_.forEach((listener, id) => { listener(newPage); - } + }); } /** @@ -117,7 +155,7 @@ cr.define('extensions', function() { let path; switch (entry.page) { case Page.LIST: - if (entry.type && entry.type == extensions.ShowingType.APPS) + if (entry.type == extensions.ShowingType.APPS) path = '/apps'; else path = '/'; @@ -157,6 +195,8 @@ cr.define('extensions', function() { const navigation = new NavigationHelper(); return { + // Constructor exposed for testing purposes. + NavigationHelper: NavigationHelper, navigation: navigation, }; }); diff --git a/chromium/chrome/browser/resources/md_extensions/options_dialog.html b/chromium/chrome/browser/resources/md_extensions/options_dialog.html index e7029bf8c76..8dd57e9fd69 100644 --- a/chromium/chrome/browser/resources/md_extensions/options_dialog.html +++ b/chromium/chrome/browser/resources/md_extensions/options_dialog.html @@ -3,7 +3,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://extensions/navigation_helper.html"> +<link rel="import" href="navigation_helper.html"> <dom-module id="extensions-options-dialog"> <template> @@ -40,5 +40,5 @@ </div> </dialog> </template> - <script src="chrome://extensions/options_dialog.js"></script> + <script src="options_dialog.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/pack_dialog.html b/chromium/chrome/browser/resources/md_extensions/pack_dialog.html index c793c6364c8..2e11adbdf66 100644 --- a/chromium/chrome/browser/resources/md_extensions/pack_dialog.html +++ b/chromium/chrome/browser/resources/md_extensions/pack_dialog.html @@ -2,6 +2,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_input_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> @@ -12,13 +13,10 @@ <dom-module id="extensions-pack-dialog"> <template> - <style include="cr-shared-style paper-button-style"> + <style include="cr-shared-style paper-button-style paper-input-style"> .file-input { align-items: center; display: flex; - --paper-input-container-input: { - font-size: inherit; - }; } .file-input paper-input { @@ -67,5 +65,5 @@ </extensions-pack-dialog-alert> </template> </template> - <script src="chrome://extensions/pack_dialog.js"></script> + <script src="pack_dialog.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/pack_dialog.js b/chromium/chrome/browser/resources/md_extensions/pack_dialog.js index 2f8ac643de5..de6f9b3b2e7 100644 --- a/chromium/chrome/browser/resources/md_extensions/pack_dialog.js +++ b/chromium/chrome/browser/resources/md_extensions/pack_dialog.js @@ -6,32 +6,31 @@ cr.define('extensions', function() { 'use strict'; /** @interface */ - function PackDialogDelegate() {} - - PackDialogDelegate.prototype = { + class PackDialogDelegate { /** * Opens a file browser for the user to select the root directory. * @return {Promise<string>} A promise that is resolved with the path the * user selected. */ - choosePackRootDirectory: assertNotReached, + choosePackRootDirectory() {} /** * Opens a file browser for the user to select the private key file. * @return {Promise<string>} A promise that is resolved with the path the * user selected. */ - choosePrivateKeyPath: assertNotReached, + choosePrivateKeyPath() {} /** * Packs the extension into a .crx. * @param {string} rootPath * @param {string} keyPath * @param {number=} flag - * @param {function(chrome.developerPrivate.PackDirectoryResponse)=} callback + * @param {function(chrome.developerPrivate.PackDirectoryResponse)=} + * callback */ - packExtension: assertNotReached, - }; + packExtension(rootPath, keyPath, flag, callback) {} + } const PackDialog = Polymer({ is: 'extensions-pack-dialog', diff --git a/chromium/chrome/browser/resources/md_extensions/pack_dialog_alert.html b/chromium/chrome/browser/resources/md_extensions/pack_dialog_alert.html index 81810d8bcad..11db084bd02 100644 --- a/chromium/chrome/browser/resources/md_extensions/pack_dialog_alert.html +++ b/chromium/chrome/browser/resources/md_extensions/pack_dialog_alert.html @@ -29,5 +29,5 @@ </div> </dialog> </template> - <script src="chrome://extensions/pack_dialog_alert.js"></script> + <script src="pack_dialog_alert.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/service.html b/chromium/chrome/browser/resources/md_extensions/service.html index dd8617e16f9..91b8058c5a1 100644 --- a/chromium/chrome/browser/resources/md_extensions/service.html +++ b/chromium/chrome/browser/resources/md_extensions/service.html @@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://extensions/service.html"> -<link rel="import" href="chrome://extensions/item.html"> -<link rel="import" href="chrome://extensions/navigation_helper.html"> -<script src="chrome://extensions/service.js"></script> +<link rel="import" href="service.html"> +<link rel="import" href="strings.html"> +<link rel="import" href="item.html"> +<link rel="import" href="navigation_helper.html"> +<script src="service.js"></script> diff --git a/chromium/chrome/browser/resources/md_extensions/service.js b/chromium/chrome/browser/resources/md_extensions/service.js index a7c09cb72bf..912dd3e9f54 100644 --- a/chromium/chrome/browser/resources/md_extensions/service.js +++ b/chromium/chrome/browser/resources/md_extensions/service.js @@ -29,6 +29,14 @@ cr.define('extensions', function() { this.manager_ = manager; this.manager_.set('delegate', this); + // Skip any setup or backend requests if we're in guest-mode. + // TODO(scottchen): there might be a better place to do this once manager + // and service become less coupled. + if (loadTimeData.getBoolean('isGuest')) { + this.manager_.initPage(); + return; + } + const keyboardShortcuts = this.manager_.keyboardShortcuts; keyboardShortcuts.addEventListener( 'shortcut-updated', this.onExtensionCommandUpdated_.bind(this)); @@ -317,6 +325,11 @@ cr.define('extensions', function() { }); }); } + + /** @override */ + openDevTools(args) { + chrome.developerPrivate.openDevTools(args); + } } cr.addSingletonGetter(Service); diff --git a/chromium/chrome/browser/resources/md_extensions/shortcut_input.html b/chromium/chrome/browser/resources/md_extensions/shortcut_input.html index 5535af64475..faf98ef6f44 100644 --- a/chromium/chrome/browser/resources/md_extensions/shortcut_input.html +++ b/chromium/chrome/browser/resources/md_extensions/shortcut_input.html @@ -2,16 +2,18 @@ <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_input_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="chrome://extensions/shortcut_util.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> +<link rel="import" href="shortcut_util.html"> <dom-module id="extensions-shortcut-input"> <template> - <style include="cr-icons cr-hidden-style"> + <style include="cr-icons cr-hidden-style paper-input-style"> #main { position: relative; width: 200px; @@ -19,13 +21,10 @@ #input { --paper-input-container: { - margin-bottom: 12px; + margin-bottom: 0px; + margin-top: 2px; /* Offset underline spacing. */ padding: 0; - }; - --paper-input-container-color: var(--paper-grey-400); - --paper-input-container-focus-color: var(--google-blue-500); - --paper-input-container-input: { - font-size: inherit; + @apply(--cr-primary-text); }; } @@ -38,7 +37,8 @@ </style> <div id="main"> <paper-input id="input" placeholder="$i18n{shortcutTypeAShortcut}" - value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]"> + value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]" + no-label-float> </paper-input> <button id="clear" is="paper-icon-button-light" class="icon-clear no-overlap" on-tap="onClearTap_" @@ -46,5 +46,5 @@ </button> </div> </template> - <script src="chrome://extensions/shortcut_input.js"></script> + <script src="shortcut_input.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/shortcut_input.js b/chromium/chrome/browser/resources/md_extensions/shortcut_input.js index f2a834ece85..a6abd7b3e75 100644 --- a/chromium/chrome/browser/resources/md_extensions/shortcut_input.js +++ b/chromium/chrome/browser/resources/md_extensions/shortcut_input.js @@ -143,9 +143,9 @@ cr.define('extensions', function() { * @private */ computeText_: function() { - if (this.capturing_) - return this.pendingShortcut_; - return this.shortcut; + let shortcutString = + this.capturing_ ? this.pendingShortcut_ : this.shortcut; + return shortcutString.split('+').join(' + '); }, /** diff --git a/chromium/chrome/browser/resources/md_extensions/shortcut_util.html b/chromium/chrome/browser/resources/md_extensions/shortcut_util.html new file mode 100644 index 00000000000..e44359faac7 --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/shortcut_util.html @@ -0,0 +1,3 @@ +<link rel="import" href="chrome://resources/html/assert.html"> +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="shortcut_util.js"></script> diff --git a/chromium/chrome/browser/resources/md_extensions/shortcut_util.js b/chromium/chrome/browser/resources/md_extensions/shortcut_util.js new file mode 100644 index 00000000000..75f235cedbb --- /dev/null +++ b/chromium/chrome/browser/resources/md_extensions/shortcut_util.js @@ -0,0 +1,196 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('extensions', function() { + 'use strict'; + + /** @enum {number} */ + const Key = { + Comma: 188, + Del: 46, + Down: 40, + End: 35, + Escape: 27, + Home: 36, + Ins: 45, + Left: 37, + MediaNextTrack: 176, + MediaPlayPause: 179, + MediaPrevTrack: 177, + MediaStop: 178, + PageDown: 34, + PageUp: 33, + Period: 190, + Right: 39, + Space: 32, + Tab: 9, + Up: 38, + }; + + /** + * Enum for whether we require modifiers of a keycode. + * @enum {number} + */ + const ModifierPolicy = {NOT_ALLOWED: 0, REQUIRED: 1}; + + /** + * Gets the ModifierPolicy. Currently only "MediaNextTrack", "MediaPrevTrack", + * "MediaStop", "MediaPlayPause" are required to be used without any modifier. + * @param {number} keyCode + * @return {ModifierPolicy} + */ + function getModifierPolicy(keyCode) { + switch (keyCode) { + case Key.MediaNextTrack: + case Key.MediaPlayPause: + case Key.MediaPrevTrack: + case Key.MediaStop: + return ModifierPolicy.NOT_ALLOWED; + default: + return ModifierPolicy.REQUIRED; + } + } + + /** + * Returns whether the keyboard event has a key modifier, which could affect + * how it's handled. + * @param {!KeyboardEvent} e + * @param {boolean} countShiftAsModifier Whether the 'Shift' key should be + * counted as modifier. + * @return {boolean} True if the event has any modifiers. + */ + function hasModifier(e, countShiftAsModifier) { + return e.ctrlKey || e.altKey || + // Meta key is only relevant on Mac and CrOS, where we treat Command + // and Search (respectively) as modifiers. + (cr.isMac && e.metaKey) || (cr.isChromeOS && e.metaKey) || + (countShiftAsModifier && e.shiftKey); + } + + /** + * Checks whether the passed in |keyCode| is a valid extension command key. + * @param {number} keyCode + * @return {boolean} Whether the key is valid. + */ + function isValidKeyCode(keyCode) { + if (keyCode == Key.Escape) + return false; + for (let k in Key) { + if (Key[k] == keyCode) + return true; + } + return (keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0)) || + (keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0)); + } + + /** + * Converts a keystroke event to string form, ignoring invalid extension + * commands. + * @param {!KeyboardEvent} e + * @return {string} The keystroke as a string. + */ + function keystrokeToString(e) { + let output = []; + // TODO(devlin): Should this be i18n'd? + if (cr.isMac && e.metaKey) + output.push('Command'); + if (cr.isChromeOS && e.metaKey) + output.push('Search'); + if (e.ctrlKey) + output.push('Ctrl'); + if (!e.ctrlKey && e.altKey) + output.push('Alt'); + if (e.shiftKey) + output.push('Shift'); + + let keyCode = e.keyCode; + if (isValidKeyCode(keyCode)) { + if ((keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0)) || + (keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0))) { + output.push(String.fromCharCode(keyCode)); + } else { + switch (keyCode) { + case Key.Comma: + output.push('Comma'); + break; + case Key.Del: + output.push('Delete'); + break; + case Key.Down: + output.push('Down'); + break; + case Key.End: + output.push('End'); + break; + case Key.Home: + output.push('Home'); + break; + case Key.Ins: + output.push('Insert'); + break; + case Key.Left: + output.push('Left'); + break; + case Key.MediaNextTrack: + output.push('MediaNextTrack'); + break; + case Key.MediaPlayPause: + output.push('MediaPlayPause'); + break; + case Key.MediaPrevTrack: + output.push('MediaPrevTrack'); + break; + case Key.MediaStop: + output.push('MediaStop'); + break; + case Key.PageDown: + output.push('PageDown'); + break; + case Key.PageUp: + output.push('PageUp'); + break; + case Key.Period: + output.push('Period'); + break; + case Key.Right: + output.push('Right'); + break; + case Key.Space: + output.push('Space'); + break; + case Key.Tab: + output.push('Tab'); + break; + case Key.Up: + output.push('Up'); + break; + } + } + } + + return output.join('+'); + } + + /** + * Returns true if the event has valid modifiers. + * @param {!KeyboardEvent} e The keyboard event to consider. + * @return {boolean} True if the event is valid. + */ + function hasValidModifiers(e) { + switch (getModifierPolicy(e.keyCode)) { + case ModifierPolicy.REQUIRED: + return hasModifier(e, false); + case ModifierPolicy.NOT_ALLOWED: + return !hasModifier(e, true); + } + assertNotReached(); + } + + return { + isValidKeyCode: isValidKeyCode, + keystrokeToString: keystrokeToString, + hasValidModifiers: hasValidModifiers, + Key: Key, + }; +}); diff --git a/chromium/chrome/browser/resources/md_extensions/sidebar.html b/chromium/chrome/browser/resources/md_extensions/sidebar.html index 030c5c10243..bd1887dd6fd 100644 --- a/chromium/chrome/browser/resources/md_extensions/sidebar.html +++ b/chromium/chrome/browser/resources/md_extensions/sidebar.html @@ -50,7 +50,7 @@ width: 15px; } </style> - <paper-menu id="section-menu" selected="0"> + <paper-menu id="section-menu" selected="{{selected_}}"> <paper-item class="section-item" id="sections-extensions" on-tap="onExtensionsTap_"> <span>$i18n{sidebarExtensions}</span> @@ -70,5 +70,5 @@ <button class="open-in-new" is="paper-icon-button-light"></button> </a> </template> - <script src="chrome://extensions/sidebar.js"></script> + <script src="sidebar.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/sidebar.js b/chromium/chrome/browser/resources/md_extensions/sidebar.js index c81d9193804..a2fea0dfc20 100644 --- a/chromium/chrome/browser/resources/md_extensions/sidebar.js +++ b/chromium/chrome/browser/resources/md_extensions/sidebar.js @@ -5,7 +5,17 @@ cr.define('extensions', function() { const Sidebar = Polymer({ is: 'extensions-sidebar', - behaviors: [I18nBehavior], + properties: { + /** @private {number} */ + selected_: { + type: Number, + value: -1, + }, + }, + + hostAttributes: { + role: 'navigation', + }, /** @private */ onExtensionsTap_: function() { @@ -23,6 +33,30 @@ cr.define('extensions', function() { onKeyboardShortcutsTap_: function() { extensions.navigation.navigateTo({page: Page.SHORTCUTS}); }, + + /** + * @param {!PageState} state + */ + updateSelected: function(state) { + let selected; + + switch (state.page) { + case Page.LIST: + if (state.type == extensions.ShowingType.APPS) + selected = 1; + else + selected = 0; + break; + case Page.SHORTCUTS: + selected = 2; + break; + default: + selected = -1; + break; + } + + this.selected_ = selected; + }, }); return {Sidebar: Sidebar}; diff --git a/chromium/chrome/browser/resources/md_extensions/strings.html b/chromium/chrome/browser/resources/md_extensions/strings.html index ada163e717b..cdc7c9b2a5b 100644 --- a/chromium/chrome/browser/resources/md_extensions/strings.html +++ b/chromium/chrome/browser/resources/md_extensions/strings.html @@ -1,2 +1,2 @@ <link rel="import" href="chrome://resources/html/load_time_data.html"> -<script src="chrome://extensions/strings.js"></script> +<script src="strings.js"></script> diff --git a/chromium/chrome/browser/resources/md_extensions/toolbar.html b/chromium/chrome/browser/resources/md_extensions/toolbar.html index 20d8d952a80..c57b165e06f 100644 --- a/chromium/chrome/browser/resources/md_extensions/toolbar.html +++ b/chromium/chrome/browser/resources/md_extensions/toolbar.html @@ -1,19 +1,18 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html"> <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> -<link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> -<link rel="import" href="chrome://extensions/icons.html"> +<link rel="import" href="icons.html"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <dom-module id="extensions-toolbar"> <template> - <style include="cr-hidden-style paper-button-style paper-toggle-style"> + <style include="cr-hidden-style paper-button-style"> :host { --toolbar-width: 580px; --toolbar-color: var(--md-toolbar-color); @@ -25,15 +24,11 @@ } /* This toggle needs special styling because it's on blue background. */ - cr-toolbar paper-toggle-button { - --paper-toggle-button-checked-bar: { - @apply(--cr-toggle-bar-size); - opacity: 0.5; - }; - --paper-toggle-button-checked-bar-color: white; - --paper-toggle-button-checked-button-color: white; - --paper-toggle-button-checked-ink-color: white; - --paper-toggle-button-unchecked-ink-color: white; + cr-toolbar cr-toggle { + --cr-toggle-checked-bar-color: white; + --cr-toggle-checked-button-color: white; + --cr-toggle-checked-ink-color: white; + --cr-toggle-unchecked-ink-color: white; } .dev-controls { @@ -66,16 +61,16 @@ -webkit-margin-end: 16px; } </style> - <cr-toolbar class="paper-header" - page-name="$i18n{toolbarTitle}" + <cr-toolbar page-name="$i18n{toolbarTitle}" search-prompt="$i18n{search}" clear-label="$i18n{clearSearch}" - show-menu> - <div class="more-actions"> - <span>$i18n{toolbarDevMode}</span> - <paper-toggle-button id="dev-mode" on-change="onDevModeChange_" - checked="[[inDevMode]]"> - </paper-toggle-button> + menu-label="$i18n{mainMenu}" + show-menu="[[!isGuest]]" show-search="[[!isGuest]]"> + <div class="more-actions" hidden$="[[isGuest]]"> + <span id="devModeLabel">$i18n{toolbarDevMode}</span> + <cr-toggle id="dev-mode" on-change="onDevModeChange_" + checked="[[inDevMode]]" aria-labelledby="devModeLabel"> + </cr-toggle> </div> </cr-toolbar> <div class="dev-controls" hidden$="[[!inDevMode]]"> @@ -89,8 +84,14 @@ <paper-button id="update-now" on-tap="onUpdateNowTap_"> $i18n{toolbarUpdateNow} </paper-button> +<if expr="chromeos"> + <paper-button id="kiosk-extensions" on-tap="onKioskTap_" + hidden$="[[!kioskEnabled]]"> + $i18n{manageKioskApp} + </paper-button> +</if> </div> </div> </template> - <script src="chrome://extensions/toolbar.js"></script> + <script src="toolbar.js"></script> </dom-module> diff --git a/chromium/chrome/browser/resources/md_extensions/toolbar.js b/chromium/chrome/browser/resources/md_extensions/toolbar.js index f7e5051491f..f973f10ed3e 100644 --- a/chromium/chrome/browser/resources/md_extensions/toolbar.js +++ b/chromium/chrome/browser/resources/md_extensions/toolbar.js @@ -6,21 +6,19 @@ cr.exportPath('extensions'); cr.define('extensions', function() { /** @interface */ - const ToolbarDelegate = function() {}; - - ToolbarDelegate.prototype = { + class ToolbarDelegate { /** * Toggles whether or not the profile is in developer mode. * @param {boolean} inDevMode */ - setProfileInDevMode: assertNotReached, + setProfileInDevMode(inDevMode) {} /** Opens the dialog to load unpacked extensions. */ - loadUnpacked: assertNotReached, + loadUnpacked() {} /** Updates all extensions. */ - updateAllExtensions: assertNotReached, - }; + updateAllExtensions() {} + } const Toolbar = Polymer({ is: 'extensions-toolbar', @@ -35,6 +33,16 @@ cr.define('extensions', function() { type: Boolean, value: false, }, + + isGuest: Boolean, + + // <if expr="chromeos"> + kioskEnabled: Boolean, + // </if> + }, + + hostAttributes: { + role: 'banner', }, /** @private */ @@ -52,6 +60,13 @@ cr.define('extensions', function() { this.fire('pack-tap'); }, + // <if expr="chromeos"> + /** @private */ + onKioskTap_: function() { + this.fire('kiosk-tap'); + }, + // </if> + /** @private */ onUpdateNowTap_: function() { this.delegate.updateAllExtensions(); diff --git a/chromium/chrome/browser/resources/md_extensions/view_manager.html b/chromium/chrome/browser/resources/md_extensions/view_manager.html index 75a6207af57..8b2bf6f82ac 100644 --- a/chromium/chrome/browser/resources/md_extensions/view_manager.html +++ b/chromium/chrome/browser/resources/md_extensions/view_manager.html @@ -22,5 +22,5 @@ </style> <slot name="view"></slot> </template> - <script src="chrome://extensions/view_manager.js"></script> -</dom-module>
\ No newline at end of file + <script src="view_manager.js"></script> +</dom-module> |