summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/resources/extensions
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-08-14 11:38:45 +0200
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-08-14 17:16:47 +0000
commit3a97ca8dd9b96b599ae2d33e40df0dd2f7ea5859 (patch)
tree43cc572ba067417c7341db81f71ae7cc6e0fcc3e /chromium/chrome/browser/resources/extensions
parentf61ab1ac7f855cd281809255c0aedbb1895e1823 (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')
-rw-r--r--chromium/chrome/browser/resources/extensions/OWNERS3
-rw-r--r--chromium/chrome/browser/resources/extensions/compiled_resources.gyp6
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_command_list.js107
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_commands_overlay.js42
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_error_overlay.js6
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_error_severity_fatal.pngbin221 -> 218 bytes
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_error_severity_info.pngbin305 -> 304 bytes
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_error_severity_warning.pngbin246 -> 242 bytes
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_list.js70
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_options_overlay.js33
-rw-r--r--chromium/chrome/browser/resources/extensions/extensions.css22
-rw-r--r--chromium/chrome/browser/resources/extensions/extensions.html9
-rw-r--r--chromium/chrome/browser/resources/extensions/extensions.js87
-rw-r--r--chromium/chrome/browser/resources/extensions/pack_extension_overlay.js5
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
index 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
Binary files differ
diff --git a/chromium/chrome/browser/resources/extensions/extension_error_severity_info.png b/chromium/chrome/browser/resources/extensions/extension_error_severity_info.png
index 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
Binary files differ
diff --git a/chromium/chrome/browser/resources/extensions/extension_error_severity_warning.png b/chromium/chrome/browser/resources/extensions/extension_error_severity_warning.png
index 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
Binary files differ
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',