Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 cr.define('extensions', function() { | 5 cr.define('extensions', function() { |
| 6 'use strict'; | 6 'use strict'; |
| 7 | 7 |
| 8 /** | 8 /** |
| 9 * Clone a template within the extension error template collection. | 9 * Clone a template within the extension error template collection. |
| 10 * @param {string} templateName The class name of the template to clone. | 10 * @param {string} templateName The class name of the template to clone. |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 * @param {string} id The Extension ID to test. | 21 * @param {string} id The Extension ID to test. |
| 22 * @return {boolean} Whether or not the ID is valid. | 22 * @return {boolean} Whether or not the ID is valid. |
| 23 */ | 23 */ |
| 24 function idIsValid(id) { | 24 function idIsValid(id) { |
| 25 return /^[a-p]{32}$/.test(id); | 25 return /^[a-p]{32}$/.test(id); |
| 26 } | 26 } |
| 27 | 27 |
| 28 /** | 28 /** |
| 29 * Creates a new ExtensionError HTMLElement; this is used to show a | 29 * Creates a new ExtensionError HTMLElement; this is used to show a |
| 30 * notification to the user when an error is caused by an extension. | 30 * notification to the user when an error is caused by an extension. |
| 31 * @param {Object} error The error the element should represent. | 31 * @param {RuntimeError} error The error the element should represent. |
| 32 * @constructor | 32 * @constructor |
| 33 * @extends {HTMLDivElement} | 33 * @extends {cr.ui.FocusRow} |
| 34 */ | 34 */ |
| 35 function ExtensionError(error) { | 35 function ExtensionError(error, boundary) { |
| 36 var div = cloneTemplate('extension-error-metadata'); | 36 var div = cloneTemplate('extension-error-metadata'); |
| 37 div.__proto__ = ExtensionError.prototype; | 37 div.__proto__ = ExtensionError.prototype; |
| 38 div.decorate(error); | 38 div.decorate(error, boundary); |
| 39 return div; | 39 return div; |
| 40 } | 40 } |
| 41 | 41 |
| 42 ExtensionError.prototype = { | 42 ExtensionError.prototype = { |
| 43 __proto__: HTMLDivElement.prototype, | 43 __proto__: cr.ui.FocusRow.prototype, |
| 44 | |
| 45 /** @override */ | |
| 46 getEquivalentElement: function(element) { | |
| 47 return assertInstanceof( | |
| 48 this.querySelector('.extension-error-view-details'), Element); | |
| 49 }, | |
| 44 | 50 |
| 45 /** | 51 /** |
| 46 * @param {RuntimeError} error | 52 * @param {RuntimeError} error The error the element should represent |
| 53 * @param {Element} boundary The boundary for the FocusGrid. | |
| 54 * @override | |
| 47 */ | 55 */ |
| 48 decorate: function(error) { | 56 decorate: function(error, boundary) { |
| 57 cr.ui.FocusRow.prototype.decorate.call( | |
| 58 assertInstanceof(this, cr.ui.FocusRow), boundary); | |
|
Dan Beam
2015/02/19 19:26:27
why are you using assertInstanceOf() here? have w
hcarmona
2015/02/19 23:42:16
This was left over from before I updated the @exte
| |
| 59 | |
| 49 // Add an additional class for the severity level. | 60 // Add an additional class for the severity level. |
| 50 if (error.level == 0) | 61 if (error.level == 0) |
| 51 this.classList.add('extension-error-severity-info'); | 62 this.classList.add('extension-error-severity-info'); |
| 52 else if (error.level == 1) | 63 else if (error.level == 1) |
| 53 this.classList.add('extension-error-severity-warning'); | 64 this.classList.add('extension-error-severity-warning'); |
| 54 else | 65 else |
| 55 this.classList.add('extension-error-severity-fatal'); | 66 this.classList.add('extension-error-severity-fatal'); |
| 56 | 67 |
| 57 var iconNode = document.createElement('img'); | 68 var iconNode = document.createElement('img'); |
| 58 iconNode.className = 'extension-error-icon'; | 69 iconNode.className = 'extension-error-icon'; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 72 viewDetailsLink.hidden = true; | 83 viewDetailsLink.hidden = true; |
| 73 } else { | 84 } else { |
| 74 var stringId = extensionUrl.toLowerCase() == 'manifest.json' ? | 85 var stringId = extensionUrl.toLowerCase() == 'manifest.json' ? |
| 75 'extensionErrorViewManifest' : 'extensionErrorViewDetails'; | 86 'extensionErrorViewManifest' : 'extensionErrorViewDetails'; |
| 76 viewDetailsLink.textContent = loadTimeData.getString(stringId); | 87 viewDetailsLink.textContent = loadTimeData.getString(stringId); |
| 77 | 88 |
| 78 viewDetailsLink.addEventListener('click', function(e) { | 89 viewDetailsLink.addEventListener('click', function(e) { |
| 79 extensions.ExtensionErrorOverlay.getInstance().setErrorAndShowOverlay( | 90 extensions.ExtensionErrorOverlay.getInstance().setErrorAndShowOverlay( |
| 80 error, extensionUrl); | 91 error, extensionUrl); |
| 81 }); | 92 }); |
| 93 | |
| 94 this.addFocusableElement(viewDetailsLink); | |
| 82 } | 95 } |
| 83 }, | 96 }, |
| 84 }; | 97 }; |
| 85 | 98 |
| 86 /** | 99 /** |
| 87 * A variable length list of runtime or manifest errors for a given extension. | 100 * A variable length list of runtime or manifest errors for a given extension. |
| 88 * @param {Array<Object>} errors The list of extension errors with which | 101 * @param {Array<Object>} errors The list of extension errors with which |
| 89 * to populate the list. | 102 * to populate the list. |
| 90 * @constructor | 103 * @constructor |
| 91 * @extends {HTMLDivElement} | 104 * @extends {HTMLDivElement} |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 102 * @private | 115 * @private |
| 103 * @const | 116 * @const |
| 104 * @type {number} | 117 * @type {number} |
| 105 */ | 118 */ |
| 106 ExtensionErrorList.MAX_ERRORS_TO_SHOW_ = 3; | 119 ExtensionErrorList.MAX_ERRORS_TO_SHOW_ = 3; |
| 107 | 120 |
| 108 ExtensionErrorList.prototype = { | 121 ExtensionErrorList.prototype = { |
| 109 __proto__: HTMLDivElement.prototype, | 122 __proto__: HTMLDivElement.prototype, |
| 110 | 123 |
| 111 decorate: function() { | 124 decorate: function() { |
| 125 this.focusGrid_ = new cr.ui.FocusGrid(); | |
| 112 this.contents_ = this.querySelector('.extension-error-list-contents'); | 126 this.contents_ = this.querySelector('.extension-error-list-contents'); |
| 127 this.contents_.addEventListener('focus', this.focusContents_.bind(this)); | |
|
Dan Beam
2015/02/19 19:26:27
onFocus_ or onFocusContents_
hcarmona
2015/02/19 23:42:17
Done.
| |
| 128 this.contents_.addEventListener('focusin', | |
| 129 this.focusinContents_.bind(this)); | |
|
Dan Beam
2015/02/19 19:26:27
onFocusin_ or onFocusinContents_
hcarmona
2015/02/19 23:42:16
Done.
| |
| 113 this.errors_.forEach(function(error) { | 130 this.errors_.forEach(function(error) { |
| 114 if (idIsValid(error.extensionId)) { | 131 if (idIsValid(error.extensionId)) { |
| 132 var focusRow = new ExtensionError(error, this.contents_); | |
| 115 this.contents_.appendChild(document.createElement('li')).appendChild( | 133 this.contents_.appendChild(document.createElement('li')).appendChild( |
| 116 new ExtensionError(error)); | 134 focusRow); |
| 135 this.focusGrid_.addRow(focusRow); | |
| 117 } | 136 } |
| 118 }, this); | 137 }, this); |
| 119 | 138 |
| 120 var numShowing = this.contents_.children.length; | 139 var numShowing = this.contents_.children.length; |
| 121 if (numShowing > ExtensionErrorList.MAX_ERRORS_TO_SHOW_) | 140 if (numShowing > ExtensionErrorList.MAX_ERRORS_TO_SHOW_) |
| 122 this.initShowMoreLink_(); | 141 this.initShowMoreLink_(); |
| 123 }, | 142 }, |
| 124 | 143 |
| 125 /** | 144 /** |
| 145 * @return {?Element} The "Show more" element or null if it's hidden. | |
| 146 */ | |
| 147 getToggleElement: function() { | |
| 148 var more = this.querySelector( | |
| 149 '.extension-error-list-show-more [is="action-link"]'); | |
|
Dan Beam
2015/02/19 19:26:28
return this.querySelector(
'.extension-error-l
hcarmona
2015/02/19 23:42:17
Done.
| |
| 150 if (!more.hidden) | |
| 151 return more; | |
| 152 return null; | |
| 153 }, | |
| 154 | |
| 155 /** | |
| 156 * @return {Element} The boundary for the FocusGrid. | |
|
Dan Beam
2015/02/19 19:26:28
nit: 1-line -> /** ... */
hcarmona
2015/02/19 23:42:16
Done.
| |
| 157 */ | |
| 158 getListElement: function() { | |
|
Dan Beam
2015/02/19 19:26:28
getFocusGridBoundary?
hcarmona
2015/02/19 23:42:16
Updated doc. Only this class needs to know it's th
| |
| 159 return this.contents_; | |
| 160 }, | |
| 161 | |
| 162 /** | |
| 163 * This element should not be focusable once this element or an element | |
| 164 * inside is it is focused. This is necessary to allow tabbing out of the | |
| 165 * grid in reverse. | |
|
Dan Beam
2015/02/19 19:26:28
rewrite doc comment without using "this" as much (
hcarmona
2015/02/19 23:42:17
Done.
| |
| 166 * @private | |
| 167 */ | |
| 168 focusinContents_: function() { | |
| 169 this.contents_.tabIndex = -1; | |
| 170 }, | |
| 171 | |
| 172 /** | |
| 173 * Focus the first focusable row when tabbing into the grid for the | |
| 174 * first time. | |
| 175 * @private | |
| 176 */ | |
| 177 focusContents_: function() { | |
| 178 var activeRow = this.contents_.querySelector('.focus-row-active'); | |
| 179 var toggleButton = this.getToggleElement(); | |
| 180 | |
| 181 if (!toggleButton || toggleButton.isShowingAll) { | |
| 182 if (activeRow) | |
|
Dan Beam
2015/02/19 19:26:27
activeRow = activeRow ||
this.contents_.queryS
hcarmona
2015/02/19 23:42:17
Done.
| |
| 183 activeRow.getEquivalentElement(null).focus(); | |
| 184 else { | |
|
Dan Beam
2015/02/19 19:26:28
conditionals can either have 0 curlies or ALL curl
hcarmona
2015/02/19 23:42:17
Done.
| |
| 185 activeRow = this.contents_.querySelector('.extension-error-metadata'); | |
|
Dan Beam
2015/02/19 19:26:28
why doesn't focusgrid have a way of accessing rows
hcarmona
2015/02/19 23:42:16
It does! :D And using that simplifies this code si
| |
| 186 activeRow.getEquivalentElement(null).focus(); | |
| 187 } | |
| 188 } else { | |
| 189 var firstVisibleChildIndex = this.contents_.children.length - | |
| 190 ExtensionErrorList.MAX_ERRORS_TO_SHOW_; | |
| 191 | |
| 192 for (var i = firstVisibleChildIndex; i < this.contents_.children.length; | |
| 193 ++i) { | |
| 194 var child = this.contents_.children[i].querySelector( | |
| 195 '.extension-error-metadata'); | |
| 196 if (child == activeRow) { | |
| 197 activeRow.getEquivalentElement(null).focus(); | |
| 198 return; | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 activeRow = this.contents_.children[firstVisibleChildIndex]. | |
| 203 querySelector('.extension-error-metadata'); | |
|
Dan Beam
2015/02/19 19:26:28
wrong indent
hcarmona
2015/02/19 23:42:16
Done.
| |
| 204 activeRow.getEquivalentElement(null).focus(); | |
| 205 } | |
| 206 }, | |
| 207 | |
| 208 /** | |
| 126 * Initialize the "Show More" link for the error list. If there are more | 209 * Initialize the "Show More" link for the error list. If there are more |
| 127 * than |MAX_ERRORS_TO_SHOW_| errors in the list. | 210 * than |MAX_ERRORS_TO_SHOW_| errors in the list. |
| 128 * @private | 211 * @private |
| 129 */ | 212 */ |
| 130 initShowMoreLink_: function() { | 213 initShowMoreLink_: function() { |
| 131 var link = this.querySelector( | 214 var link = this.querySelector( |
| 132 '.extension-error-list-show-more [is="action-link"]'); | 215 '.extension-error-list-show-more [is="action-link"]'); |
| 133 link.hidden = false; | 216 link.hidden = false; |
| 134 link.isShowingAll = false; | 217 link.isShowingAll = false; |
| 135 | 218 |
| 136 var listContents = this.querySelector('.extension-error-list-contents'); | 219 var listContents = this.querySelector('.extension-error-list-contents'); |
| 137 | 220 |
| 138 // TODO(dbeam/kalman): trade all this transition voodoo for .animate()? | 221 // TODO(dbeam/kalman): trade all this transition voodoo for .animate()? |
| 139 listContents.addEventListener('webkitTransitionEnd', function(e) { | 222 listContents.addEventListener('webkitTransitionEnd', function(e) { |
| 140 if (listContents.classList.contains('deactivating')) | 223 if (listContents.classList.contains('deactivating')) |
| 141 listContents.classList.remove('deactivating', 'active'); | 224 listContents.classList.remove('deactivating', 'active'); |
| 142 else | 225 else |
| 143 listContents.classList.add('scrollable'); | 226 listContents.classList.add('scrollable'); |
| 144 }); | 227 }); |
| 145 | 228 |
| 146 link.addEventListener('click', function(e) { | 229 link.addEventListener('click', function(e) { |
| 230 // Needs to be enabled in case the focused row is now hidden. | |
| 231 this.contents_.tabIndex = 0; | |
| 232 | |
| 147 link.isShowingAll = !link.isShowingAll; | 233 link.isShowingAll = !link.isShowingAll; |
| 148 | 234 |
| 149 var message = link.isShowingAll ? 'extensionErrorsShowFewer' : | 235 var message = link.isShowingAll ? 'extensionErrorsShowFewer' : |
| 150 'extensionErrorsShowMore'; | 236 'extensionErrorsShowMore'; |
| 151 link.textContent = loadTimeData.getString(message); | 237 link.textContent = loadTimeData.getString(message); |
| 152 | 238 |
| 153 // Disable scrolling while transitioning. If the element is active, | 239 // Disable scrolling while transitioning. If the element is active, |
| 154 // scrolling is enabled when the transition ends. | 240 // scrolling is enabled when the transition ends. |
| 155 listContents.classList.remove('scrollable'); | 241 listContents.classList.remove('scrollable'); |
| 156 | 242 |
| 157 if (link.isShowingAll) { | 243 if (link.isShowingAll) { |
| 158 listContents.classList.add('active'); | 244 listContents.classList.add('active'); |
| 159 listContents.classList.remove('deactivating'); | 245 listContents.classList.remove('deactivating'); |
| 160 } else { | 246 } else { |
| 161 listContents.classList.add('deactivating'); | 247 listContents.classList.add('deactivating'); |
| 162 } | 248 } |
| 163 }.bind(this)); | 249 }.bind(this)); |
| 164 } | 250 } |
| 165 }; | 251 }; |
| 166 | 252 |
| 167 return { | 253 return { |
| 168 ExtensionErrorList: ExtensionErrorList | 254 ExtensionErrorList: ExtensionErrorList |
| 169 }; | 255 }; |
| 170 }); | 256 }); |
| OLD | NEW |