diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-08-14 11:38:45 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-08-14 17:16:47 +0000 |
commit | 3a97ca8dd9b96b599ae2d33e40df0dd2f7ea5859 (patch) | |
tree | 43cc572ba067417c7341db81f71ae7cc6e0fcc3e /chromium/chrome/browser/resources/extensions | |
parent | f61ab1ac7f855cd281809255c0aedbb1895e1823 (diff) |
BASELINE: Update chromium to 45.0.2454.40
Change-Id: Id2121d9f11a8fc633677236c65a3e41feef589e4
Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'chromium/chrome/browser/resources/extensions')
14 files changed, 241 insertions, 149 deletions
diff --git a/chromium/chrome/browser/resources/extensions/OWNERS b/chromium/chrome/browser/resources/extensions/OWNERS index c97faa4239e..9fb4aea29dc 100644 --- a/chromium/chrome/browser/resources/extensions/OWNERS +++ b/chromium/chrome/browser/resources/extensions/OWNERS @@ -1,3 +1,4 @@ +dbeam@chromium.org finnur@chromium.org kalman@chromium.org -miket@chromium.org +rdevlin.cronin@chromium.org diff --git a/chromium/chrome/browser/resources/extensions/compiled_resources.gyp b/chromium/chrome/browser/resources/extensions/compiled_resources.gyp index 23f5dd0f3d3..e6127bf181a 100644 --- a/chromium/chrome/browser/resources/extensions/compiled_resources.gyp +++ b/chromium/chrome/browser/resources/extensions/compiled_resources.gyp @@ -31,9 +31,9 @@ '../../../../ui/webui/resources/js/util.js', ], 'externs': [ - '<(CLOSURE_DIR)/externs/chrome_extensions.js', - '<(CLOSURE_DIR)/externs/chrome_send_externs.js', - '<(CLOSURE_DIR)/externs/developer_private.js', + '<(EXTERNS_DIR)/chrome_extensions.js', + '<(EXTERNS_DIR)/chrome_send.js', + '<(EXTERNS_DIR)/developer_private.js', ], }, 'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'], diff --git a/chromium/chrome/browser/resources/extensions/extension_command_list.js b/chromium/chrome/browser/resources/extensions/extension_command_list.js index 0a184dc8330..9974fb72da9 100644 --- a/chromium/chrome/browser/resources/extensions/extension_command_list.js +++ b/chromium/chrome/browser/resources/extensions/extension_command_list.js @@ -15,14 +15,6 @@ var ExtensionCommand; cr.define('options', function() { 'use strict'; - /** - * Creates a new list of extension commands. - * @param {Object=} opt_propertyBag Optional properties. - * @constructor - * @extends {HTMLDivElement} - */ - var ExtensionCommandList = cr.ui.define('div'); - /** @const */ var keyComma = 188; /** @const */ var keyDel = 46; /** @const */ var keyDown = 40; @@ -184,6 +176,17 @@ cr.define('options', function() { (countShiftAsModifier && event.shiftKey); } + /** + * Creates a new list of extension commands. + * @param {HTMLDivElement} div + * @constructor + * @extends {HTMLDivElement} + */ + function ExtensionCommandList(div) { + div.__proto__ = ExtensionCommandList.prototype; + return div; + } + ExtensionCommandList.prototype = { __proto__: HTMLDivElement.prototype, @@ -212,20 +215,31 @@ cr.define('options', function() { */ capturingElement_: null, - decorate: function() { + /** + * Updates the extensions data for the overlay. + * @param {!Array<ExtensionInfo>} data The extension data. + */ + setData: function(data) { + /** @private {!Array<ExtensionInfo>} */ + this.data_ = data; + this.textContent = ''; // Iterate over the extension data and add each item to the list. - this.data_.commands.forEach(this.createNodeForExtension_.bind(this)); + this.data_.forEach(this.createNodeForExtension_.bind(this)); }, /** * Synthesizes and initializes an HTML element for the extension command * metadata given in |extension|. - * @param {Object} extension A dictionary of extension metadata. + * @param {ExtensionInfo} extension A dictionary of extension metadata. * @private */ createNodeForExtension_: function(extension) { + if (extension.commands.length == 0 || + extension.state == chrome.developerPrivate.ExtensionState.DISABLED) + return; + var template = $('template-collection-extension-commands').querySelector( '.extension-command-list-extension-item-wrapper'); var node = template.cloneNode(true); @@ -237,22 +251,22 @@ cr.define('options', function() { // Iterate over the commands data within the extension and add each item // to the list. - extension.commands.forEach(this.createNodeForCommand_.bind(this)); + extension.commands.forEach( + this.createNodeForCommand_.bind(this, extension.id)); }, /** * Synthesizes and initializes an HTML element for the extension command * metadata given in |command|. - * @param {ExtensionCommand} command A dictionary of extension command - * metadata. + * @param {string} extensionId The associated extension's id. + * @param {Command} command A dictionary of extension command metadata. * @private */ - createNodeForCommand_: function(command) { + createNodeForCommand_: function(extensionId, command) { var template = $('template-collection-extension-commands').querySelector( '.extension-command-list-command-item-wrapper'); var node = template.cloneNode(true); - node.id = this.createElementId_( - 'command', command.extension_id, command.command_name); + node.id = this.createElementId_('command', extensionId, command.name); var description = node.querySelector('.command-description'); description.textContent = command.description; @@ -264,7 +278,7 @@ cr.define('options', function() { shortcutNode.addEventListener('blur', this.handleBlur_.bind(this)); shortcutNode.addEventListener('keydown', this.handleKeyDown_.bind(this)); shortcutNode.addEventListener('keyup', this.handleKeyUp_.bind(this)); - if (!command.active) { + if (!command.isActive) { shortcutNode.textContent = loadTimeData.getString('extensionCommandsInactive'); @@ -276,28 +290,31 @@ cr.define('options', function() { var commandClear = node.querySelector('.command-clear'); commandClear.id = this.createElementId_( - 'clear', command.extension_id, command.command_name); + 'clear', extensionId, command.name); commandClear.title = loadTimeData.getString('extensionCommandsDelete'); commandClear.addEventListener('click', this.handleClear_.bind(this)); var select = node.querySelector('.command-scope'); select.id = this.createElementId_( - 'setCommandScope', command.extension_id, command.command_name); + 'setCommandScope', extensionId, command.name); select.hidden = false; // Add the 'In Chrome' option. var option = document.createElement('option'); option.textContent = loadTimeData.getString('extensionCommandsRegular'); select.appendChild(option); - if (command.extension_action) { + if (command.isExtensionAction || !command.isActive) { // Extension actions cannot be global, so we might as well disable the - // combo box, to signify that. + // combo box, to signify that, and if the command is inactive, it + // doesn't make sense to allow the user to adjust the scope. select.disabled = true; } else { // Add the 'Global' option. option = document.createElement('option'); option.textContent = loadTimeData.getString('extensionCommandsGlobal'); select.appendChild(option); - select.selectedIndex = command.global ? 1 : 0; + select.selectedIndex = + command.scope == chrome.developerPrivate.CommandScope.GLOBAL ? + 1 : 0; select.addEventListener( 'change', this.handleSetCommandScope_.bind(this)); @@ -316,7 +333,7 @@ cr.define('options', function() { if (this.capturingElement_) return; // Already capturing. - chrome.send('setShortcutHandlingSuspended', [true]); + chrome.developerPrivate.setShortcutHandlingSuspended(true); var shortcutNode = event.target; this.oldValue_ = shortcutNode.textContent; @@ -341,7 +358,7 @@ cr.define('options', function() { if (!this.capturingElement_) return; // Not capturing. - chrome.send('setShortcutHandlingSuspended', [false]); + chrome.developerPrivate.setShortcutHandlingSuspended(false); var shortcutNode = this.capturingElement_; var commandShortcut = shortcutNode.parentElement; @@ -402,12 +419,20 @@ cr.define('options', function() { handleKeyDown_: function(event) { event = /** @type {KeyboardEvent} */(event); if (event.keyCode == keyEscape) { - // Escape cancels capturing. + if (!this.capturingElement_) { + // If we're not currently capturing, allow escape to propagate (so it + // can close the overflow). + return; + } + // Otherwise, escape cancels capturing. this.endCapture_(event); var parsed = this.parseElementId_('clear', event.target.parentElement.querySelector('.command-clear').id); - chrome.send('setExtensionCommandShortcut', - [parsed.extensionId, parsed.commandName, '']); + chrome.developerPrivate.updateExtensionCommand({ + extensionId: parsed.extensionId, + commandName: parsed.commandName, + keybinding: '' + }); event.preventDefault(); event.stopPropagation(); return; @@ -430,8 +455,9 @@ cr.define('options', function() { */ handleKeyUp_: function(event) { event = /** @type {KeyboardEvent} */(event); - if (event.keyCode == keyTab) { - // Allow tab propagation for keyboard navigation. + if (event.keyCode == keyTab || event.keyCode == keyEscape) { + // We need to allow tab propagation for keyboard navigation, and escapes + // are fully handled in handleKeyDown. return; } @@ -496,8 +522,10 @@ cr.define('options', function() { // Ending the capture must occur before calling // setExtensionCommandShortcut to ensure the shortcut is set. this.endCapture_(event); - chrome.send('setExtensionCommandShortcut', - [parsed.extensionId, parsed.commandName, keystroke]); + chrome.developerPrivate.updateExtensionCommand( + {extensionId: parsed.extensionId, + commandName: parsed.commandName, + keybinding: keystroke}); } }, @@ -508,8 +536,10 @@ cr.define('options', function() { */ handleClear_: function(event) { var parsed = this.parseElementId_('clear', event.target.id); - chrome.send('setExtensionCommandShortcut', - [parsed.extensionId, parsed.commandName, '']); + chrome.developerPrivate.updateExtensionCommand( + {extensionId: parsed.extensionId, + commandName: parsed.commandName, + keybinding: ''}); }, /** @@ -521,8 +551,13 @@ cr.define('options', function() { var parsed = this.parseElementId_('setCommandScope', event.target.id); var element = document.getElementById( 'setCommandScope-' + parsed.extensionId + '-' + parsed.commandName); - chrome.send('setCommandScope', - [parsed.extensionId, parsed.commandName, element.selectedIndex == 1]); + var scope = element.selectedIndex == 1 ? + chrome.developerPrivate.CommandScope.GLOBAL : + chrome.developerPrivate.CommandScope.CHROME; + chrome.developerPrivate.updateExtensionCommand( + {extensionId: parsed.extensionId, + commandName: parsed.commandName, + scope: scope}); }, /** diff --git a/chromium/chrome/browser/resources/extensions/extension_commands_overlay.js b/chromium/chrome/browser/resources/extensions/extension_commands_overlay.js index a96ef44780b..9b51f341f90 100644 --- a/chromium/chrome/browser/resources/extensions/extension_commands_overlay.js +++ b/chromium/chrome/browser/resources/extensions/extension_commands_overlay.js @@ -31,12 +31,15 @@ cr.define('extensions', function() { cr.ui.overlay.globalInitialization(); overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this)); - $('extension-commands-dismiss').addEventListener('click', - this.handleDismiss_.bind(this)); + this.extensionCommandList_ = new ExtensionCommandList( + /**@type {HTMLDivElement} */($('extension-command-list'))); - // This will request the data to show on the page and will get a response - // back in returnExtensionsData. - chrome.send('extensionCommandsRequestExtensionsData'); + $('extension-commands-dismiss').addEventListener('click', function() { + cr.dispatchSimpleEvent(overlay, 'cancelOverlay'); + }); + + // The ExtensionList will update us with its data, so we don't need to + // handle that here. }, /** @@ -51,25 +54,28 @@ cr.define('extensions', function() { /** * Called by the dom_ui_ to re-populate the page with data representing * the current state of extension commands. - * @param {!{commands: Array<{name: string, id: string, commands: ?Array}>}} - * extensionsData + * @param {!Array<ExtensionInfo>} extensionsData */ - ExtensionCommandsOverlay.returnExtensionsData = function(extensionsData) { - ExtensionCommandList.prototype.data_ = extensionsData; - var extensionCommandList = $('extension-command-list'); - ExtensionCommandList.decorate(extensionCommandList); + ExtensionCommandsOverlay.updateExtensionsData = function(extensionsData) { + var overlay = ExtensionCommandsOverlay.getInstance(); + overlay.extensionCommandList_.setData(extensionsData); + + var hasAnyCommands = false; + for (var i = 0; i < extensionsData.length; ++i) { + if (extensionsData[i].commands.length > 0) { + hasAnyCommands = true; + break; + } + } // Make sure the config link is visible, since there are commands to show // and potentially configure. document.querySelector('.extension-commands-config').hidden = - extensionsData.commands.length == 0; + !hasAnyCommands; - $('no-commands').hidden = extensionsData.commands.length > 0; - var list = $('extension-command-list'); - if (extensionsData.commands.length == 0) - list.classList.add('empty-extension-commands-list'); - else - list.classList.remove('empty-extension-commands-list'); + $('no-commands').hidden = hasAnyCommands; + overlay.extensionCommandList_.classList.toggle( + 'empty-extension-commands-list', !hasAnyCommands); }; // Export diff --git a/chromium/chrome/browser/resources/extensions/extension_error_overlay.js b/chromium/chrome/browser/resources/extensions/extension_error_overlay.js index 84e32a9f63b..1f7975e6605 100644 --- a/chromium/chrome/browser/resources/extensions/extension_error_overlay.js +++ b/chromium/chrome/browser/resources/extensions/extension_error_overlay.js @@ -292,8 +292,10 @@ cr.define('extensions', function() { cr.ui.overlay.globalInitialization(); overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this)); - $('extension-error-overlay-dismiss').addEventListener( - 'click', this.handleDismiss_.bind(this)); + $('extension-error-overlay-dismiss').addEventListener('click', + function() { + cr.dispatchSimpleEvent(overlay, 'cancelOverlay'); + }); /** * The element of the full overlay. diff --git a/chromium/chrome/browser/resources/extensions/extension_error_severity_fatal.png b/chromium/chrome/browser/resources/extensions/extension_error_severity_fatal.png Binary files differindex b52a68c6026..b53dc2cf74b 100644 --- a/chromium/chrome/browser/resources/extensions/extension_error_severity_fatal.png +++ b/chromium/chrome/browser/resources/extensions/extension_error_severity_fatal.png diff --git a/chromium/chrome/browser/resources/extensions/extension_error_severity_info.png b/chromium/chrome/browser/resources/extensions/extension_error_severity_info.png Binary files differindex edc95f7cae6..1c32c6eb83f 100644 --- a/chromium/chrome/browser/resources/extensions/extension_error_severity_info.png +++ b/chromium/chrome/browser/resources/extensions/extension_error_severity_info.png diff --git a/chromium/chrome/browser/resources/extensions/extension_error_severity_warning.png b/chromium/chrome/browser/resources/extensions/extension_error_severity_warning.png Binary files differindex 67a2037799c..d2e3434a595 100644 --- a/chromium/chrome/browser/resources/extensions/extension_error_severity_warning.png +++ b/chromium/chrome/browser/resources/extensions/extension_error_severity_warning.png diff --git a/chromium/chrome/browser/resources/extensions/extension_list.js b/chromium/chrome/browser/resources/extensions/extension_list.js index b3343913c9f..d8cc1e03a9a 100644 --- a/chromium/chrome/browser/resources/extensions/extension_list.js +++ b/chromium/chrome/browser/resources/extensions/extension_list.js @@ -147,6 +147,8 @@ ExtensionFocusRow.prototype = { cr.define('extensions', function() { 'use strict'; + var ExtensionCommandsOverlay = extensions.ExtensionCommandsOverlay; + /** * Compares two extensions for the order they should appear in the list. * @param {ExtensionInfo} a The first extension. @@ -294,6 +296,18 @@ cr.define('extensions', function() { eventData.event_type == EventType.UNINSTALLED) { this.delegate_.onExtensionCountChanged(); } + + if (eventData.event_type == EventType.LOADED || + eventData.event_type == EventType.UNLOADED || + eventData.event_type == EventType.PREFS_CHANGED || + eventData.event_type == EventType.UNINSTALLED) { + // We update the commands overlay whenever an extension is added or + // removed (other updates wouldn't affect command-ly things). We + // need both UNLOADED and UNINSTALLED since the UNLOADED event results + // in an extension losing active keybindings, and UNINSTALLED can + // result in the "Keyboard shortcuts" link being removed. + ExtensionCommandsOverlay.updateExtensionsData(this.extensions_); + } }.bind(this)); }, @@ -320,6 +334,11 @@ cr.define('extensions', function() { extensions.sort(compareExtensions); this.extensions_ = extensions; this.showExtensionNodes_(); + + // We keep the commands overlay's extension info in sync, so that we + // don't duplicate the same querying logic there. + ExtensionCommandsOverlay.updateExtensionsData(this.extensions_); + resolve(); // |resolve| is async so it's necessary to use |then| here in order to @@ -639,7 +658,6 @@ cr.define('extensions', function() { var trashTemplate = $('template-collection').querySelector('.trash'); var trash = trashTemplate.cloneNode(true); trash.title = loadTimeData.getString('extensionUninstall'); - trash.hidden = !extension.userMayModify; trash.setAttribute('column-type', 'trash'); trash.addEventListener('click', function(e) { trash.classList.add('open'); @@ -702,19 +720,14 @@ cr.define('extensions', function() { // Hack to keep the closure compiler happy about |remove|. // TODO(hcarmona): Remove this hack when the closure compiler is updated. var node = /** @type {Element} */ (row); - node.classList.remove('policy-controlled', 'may-not-modify', - 'may-not-remove'); + node.classList.remove('controlled', 'may-not-remove'); var classes = []; - if (!extension.userMayModify) { - classes.push('policy-controlled', 'may-not-modify'); - } else if (extension.dependentExtensions.length > 0) { - classes.push('may-not-remove', 'may-not-modify'); - } else if (extension.mustRemainInstalled) { + if (extension.controlledInfo) { + classes.push('controlled'); + } else if (!extension.userMayModify || + extension.mustRemainInstalled || + extension.dependentExtensions.length > 0) { classes.push('may-not-remove'); - } else if (extension.disableReasons.suspiciousInstall || - extension.disableReasons.corruptInstall || - extension.disableReasons.updateRequired) { - classes.push('may-not-modify'); } row.classList.add.apply(row.classList, classes); @@ -850,32 +863,37 @@ cr.define('extensions', function() { extension.disableReasons.suspiciousInstall || extension.disableReasons.corruptInstall || extension.disableReasons.updateRequired || - extension.installedByCustodian || extension.dependentExtensions.length > 0; item.querySelector('input').disabled = enableCheckboxDisabled; item.querySelector('input').checked = isActive; }); - // Button for extensions controlled by policy. + // Indicator for extensions controlled by policy. var controlNode = row.querySelector('.enable-controls'); var indicator = controlNode.querySelector('.controlled-extension-indicator'); - var needsIndicator = isOK && - !extension.userMayModify && - extension.policyText; - // TODO(treib): If userMayModify is false, but policyText is empty, that - // indicates this extension is controlled by something else than - // enterprise policy (such as the profile being supervised). For now, just - // don't show the indicator in this case. We should really handle this - // better though (ie use a different text and icon). + var needsIndicator = isOK && extension.controlledInfo; if (needsIndicator && !indicator) { indicator = new cr.ui.ControlledIndicator(); indicator.classList.add('controlled-extension-indicator'); - indicator.setAttribute('controlled-by', 'policy'); - var textPolicy = extension.policyText || ''; - indicator.setAttribute('textpolicy', textPolicy); - indicator.image.setAttribute('aria-label', textPolicy); + var ControllerType = chrome.developerPrivate.ControllerType; + var controlledByStr = ''; + switch (extension.controlledInfo.type) { + case ControllerType.POLICY: + controlledByStr = 'policy'; + break; + case ControllerType.CHILD_CUSTODIAN: + controlledByStr = 'child-custodian'; + break; + case ControllerType.SUPERVISED_USER_CUSTODIAN: + controlledByStr = 'supervised-user-custodian'; + break; + } + indicator.setAttribute('controlled-by', controlledByStr); + var text = extension.controlledInfo.text; + indicator.setAttribute('text' + controlledByStr, text); + indicator.image.setAttribute('aria-label', text); controlNode.appendChild(indicator); indicator.querySelector('div').setAttribute('column-type', 'enterprise'); diff --git a/chromium/chrome/browser/resources/extensions/extension_options_overlay.js b/chromium/chrome/browser/resources/extensions/extension_options_overlay.js index 8c09d153afc..73aac3ed618 100644 --- a/chromium/chrome/browser/resources/extensions/extension_options_overlay.js +++ b/chromium/chrome/browser/resources/extensions/extension_options_overlay.js @@ -2,6 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Returns the width of a scrollbar in logical pixels. +function getScrollbarWidth() { + // Create nested divs with scrollbars. + var outer = document.createElement('div'); + outer.style.width = '100px'; + outer.style.overflow = 'scroll'; + outer.style.visibility = 'hidden'; + document.body.appendChild(outer); + var inner = document.createElement('div'); + inner.style.width = '101px'; + outer.appendChild(inner); + + // The outer div's |clientWidth| and |offsetWidth| differ only by the width of + // the vertical scrollbar. + var scrollbarWidth = outer.offsetWidth - outer.clientWidth; + outer.parentNode.removeChild(outer); + return scrollbarWidth; +} + cr.define('extensions', function() { 'use strict'; @@ -132,11 +151,19 @@ cr.define('extensions', function() { extensionoptions.onpreferredsizechanged = function(evt) { var oldOverlayWidth = parseInt(overlayStyle.width, 10); var oldOverlayHeight = parseInt(overlayStyle.height, 10); - var newOverlayWidth = Math.max(evt.width, minWidth); + var newOverlayWidth = evt.width; // |evt.height| is just the new overlay guest height, and does not // include the overlay header height, so it needs to be added. - var newOverlayHeight = - Math.min(evt.height + overlayHeader.offsetHeight, maxHeight); + var newOverlayHeight = evt.height + overlayHeader.offsetHeight; + + // Make room for the vertical scrollbar, if there is one. + if (newOverlayHeight > maxHeight) { + newOverlayWidth += getScrollbarWidth(); + } + + // Enforce |minWidth| and |maxHeight|. + newOverlayWidth = Math.max(newOverlayWidth, minWidth); + newOverlayHeight = Math.min(newOverlayHeight, maxHeight); // animationTime is the amount of time in ms that will be used to resize // the overlay. It is calculated by multiplying the pythagorean distance diff --git a/chromium/chrome/browser/resources/extensions/extensions.css b/chromium/chrome/browser/resources/extensions/extensions.css index 47119b78412..c94dfad6d5a 100644 --- a/chromium/chrome/browser/resources/extensions/extensions.css +++ b/chromium/chrome/browser/resources/extensions/extensions.css @@ -59,11 +59,6 @@ html:not(.focus-outline-visible) flex: 1; } -#dev-toggle { - margin-top: 0; - text-align: end; -} - .extension-code { border: 1px solid #ccc; display: flex; @@ -108,11 +103,13 @@ html:not(.focus-outline-visible) } #header-controls { - right: 13px; + /* Reserve enough space to match .location-text + .trash */ + min-width: 130px; + right: 16px; } html[dir='rtl'] #header-controls { - left: 13px; + left: 16px; right: auto; } @@ -122,7 +119,7 @@ html[dir='rtl'] #header-controls { #extension-settings #page-header { /* These values match the .page values. */ - -webkit-margin-end: 0; + -webkit-margin-end: 24px; min-width: 576px; } @@ -184,6 +181,7 @@ html[dir='rtl'] .extension-list-item { .extension-title { -webkit-padding-end: 20px; color: rgb(48, 57, 66); + display: inline; font-size: 14px; font-weight: 500; } @@ -369,6 +367,11 @@ html[dir=rtl] .extension-commands-config { width: 100px; } +.enable-checkbox { + /* Reserve enough space to match .location-text */ + min-width: 100px; +} + /* Trash */ #extension-settings .trash { @@ -378,6 +381,7 @@ html[dir=rtl] .extension-commands-config { right: -8px; top: 6px; transition: opacity 200ms; + vertical-align: top; } html[dir='rtl'] #extension-settings .trash { @@ -398,7 +402,7 @@ html[dir='rtl'] #extension-settings .trash { * remove it from the layout and make space for the controlled indicator. * TODO(cschuet): rather than hide always replace it with something meaningful. */ -.extension-list-item-wrapper.policy-controlled .trash { +.extension-list-item-wrapper.controlled .trash { display: none; } diff --git a/chromium/chrome/browser/resources/extensions/extensions.html b/chromium/chrome/browser/resources/extensions/extensions.html index fede5ebdc7a..58bbf471d84 100644 --- a/chromium/chrome/browser/resources/extensions/extensions.html +++ b/chromium/chrome/browser/resources/extensions/extensions.html @@ -16,6 +16,7 @@ <link rel="stylesheet" href="chrome://resources/css/controlled_indicator.css"> <link rel="stylesheet" href="chrome://resources/css/chrome_shared.css"> <link rel="stylesheet" href="chrome://resources/css/overlay.css"> +<link rel="stylesheet" href="chrome://resources/css/spinner.css"> <link rel="stylesheet" href="chrome://resources/css/trash.css"> <link rel="stylesheet" href="../uber/uber_shared.css"> @@ -86,7 +87,11 @@ </div> </div> </header> - <div id="dev-controls"> + <div id="loading-spinner"> + <div class="inline-spinner"></div> + <span i18n-content="loading"></span> + </div> + <div id="dev-controls" hidden> <div class="button-container"> <button id="load-unpacked" i18n-content="extensionSettingsLoadUnpackedButton"></button> @@ -128,7 +133,7 @@ <div class="extension-list-item"> <div class="extension-details"> <div> - <span class="extension-title"></span> + <h2 class="extension-title"></h2> <span class="extension-version"></span> </div> <p class="corrupt-install-message" diff --git a/chromium/chrome/browser/resources/extensions/extensions.js b/chromium/chrome/browser/resources/extensions/extensions.js index 5e1812dbf25..863d2fe6b60 100644 --- a/chromium/chrome/browser/resources/extensions/extensions.js +++ b/chromium/chrome/browser/resources/extensions/extensions.js @@ -125,17 +125,10 @@ cr.define('extensions', function() { dragEnabled_: false, /** - * Callback for testing purposes. This is called after the "Developer mode" - * checkbox is toggled and the div containing developer buttons' height has - * been set. - * @type {function()?} - */ - testingDeveloperModeCallback: null, - - /** * Perform initial setup. */ initialize: function() { + this.setLoading_(true); uber.onContentFrameLoaded(); cr.ui.FocusOutlineManager.forDocument(document); measureCheckboxStrings(); @@ -148,10 +141,12 @@ cr.define('extensions', function() { var wrapper = $('extension-list-wrapper'); wrapper.insertBefore(extensionList, wrapper.firstChild); - this.update_(); - // TODO(devlin): Remove this once all notifications are moved to events on - // the developerPrivate api. - chrome.send('extensionSettingsRegister'); + // Get the initial profile state, and register to be notified of any + // future changes. + chrome.developerPrivate.getProfileConfiguration( + this.update_.bind(this)); + chrome.developerPrivate.onProfileStateChanged.addListener( + this.update_.bind(this)); var extensionLoader = extensions.ExtensionLoader.getInstance(); @@ -240,23 +235,15 @@ cr.define('extensions', function() { }, /** - * Updates the extensions page to the latest profile and extensions - * configuration. - * @private - */ - update_: function() { - chrome.developerPrivate.getProfileConfiguration( - this.returnProfileConfiguration_.bind(this)); - }, - - /** * [Re]-Populates the page with data representing the current state of * installed extensions. * @param {ProfileInfo} profileInfo * @private */ - returnProfileConfiguration_: function(profileInfo) { + update_: function(profileInfo) { + this.setLoading_(true); webuiResponded = true; + /** @const */ var supervised = profileInfo.isSupervised; @@ -268,27 +255,33 @@ cr.define('extensions', function() { devControlsCheckbox.checked = profileInfo.inDeveloperMode; devControlsCheckbox.disabled = supervised; - this.updateDevControlsVisibility_(false); - $('load-unpacked').disabled = !profileInfo.canLoadUnpacked; var extensionList = $('extension-settings-list'); extensionList.updateExtensionsData( profileInfo.isIncognitoAvailable, profileInfo.appInfoDialogEnabled).then(function() { - // We can get called many times in short order, thus we need to - // be careful to remove the 'finished loading' timeout. - if (this.loadingTimeout_) - window.clearTimeout(this.loadingTimeout_); - document.documentElement.classList.add('loading'); - this.loadingTimeout_ = window.setTimeout(function() { - document.documentElement.classList.remove('loading'); - }, 0); - + this.setLoading_(false); this.onExtensionCountChanged(); }.bind(this)); }, /** + * Shows the loading spinner and hides elements that shouldn't be visible + * while loading. + * @param {boolean} isLoading + * @private + */ + setLoading_: function(isLoading) { + document.documentElement.classList.toggle('loading', isLoading); + $('loading-spinner').hidden = !isLoading; + $('dev-controls').hidden = isLoading; + this.updateDevControlsVisibility_(false); + + // The extension list is already hidden/shown elsewhere and shouldn't be + // updated here because it can be hidden if there are no extensions. + }, + + /** * Handles the Pack Extension button. * @param {Event} e Change event. * @private @@ -352,8 +345,7 @@ cr.define('extensions', function() { devControls.style.height = !showDevControls ? '' : buttons.offsetHeight + 'px'; - if (this.testingDeveloperModeCallback) - this.testingDeveloperModeCallback(); + document.dispatchEvent(new Event('devControlsVisibilityUpdated')); }.bind(this)); }, @@ -367,14 +359,6 @@ cr.define('extensions', function() { }; /** - * Called by the WebUI when something has changed and the extensions UI needs - * to be updated. - */ - ExtensionSettings.onExtensionsChanged = function() { - ExtensionSettings.getInstance().update_(); - }; - - /** * Returns the current overlay or null if one does not exist. * @return {Element} The overlay element. */ @@ -401,9 +385,19 @@ cr.define('extensions', function() { } if (node) { - var lastFocused = document.activeElement; + var lastFocused; + + var focusOutlineManager = cr.ui.FocusOutlineManager.forDocument(document); + if (focusOutlineManager.visible) + lastFocused = document.activeElement; + $('overlay').addEventListener('cancelOverlay', function f() { - lastFocused.focus(); + console.log('cancelOverlay'); + console.log('lastFocused', lastFocused); + console.log('focusOutlineManager.visible', focusOutlineManager.visible); + if (lastFocused && focusOutlineManager.visible) + lastFocused.focus(); + $('overlay').removeEventListener('cancelOverlay', f); }); node.classList.add('showing'); @@ -483,6 +477,5 @@ cr.define('extensions', function() { }); window.addEventListener('load', function(e) { - document.documentElement.classList.add('loading'); extensions.ExtensionSettings.getInstance().initialize(); }); diff --git a/chromium/chrome/browser/resources/extensions/pack_extension_overlay.js b/chromium/chrome/browser/resources/extensions/pack_extension_overlay.js index 03e6180a03d..05d23d1f2f9 100644 --- a/chromium/chrome/browser/resources/extensions/pack_extension_overlay.js +++ b/chromium/chrome/browser/resources/extensions/pack_extension_overlay.js @@ -23,8 +23,9 @@ cr.define('extensions', function() { cr.ui.overlay.globalInitialization(); overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this)); - $('pack-extension-dismiss').addEventListener('click', - this.handleDismiss_.bind(this)); + $('pack-extension-dismiss').addEventListener('click', function() { + cr.dispatchSimpleEvent(overlay, 'cancelOverlay'); + }); $('pack-extension-commit').addEventListener('click', this.handleCommit_.bind(this)); $('browse-extension-dir').addEventListener('click', |