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 3 // found in the LICENSE file. 4 5 <include src="extension_error_overlay.js"></include> 6 7 cr.define('extensions', function() { 8 'use strict'; 9 10 /** 11 * Clone a template within the extension error template collection. 12 * @param {string} templateName The class name of the template to clone. 13 * @return {HTMLElement} The clone of the template. 14 */ 15 function cloneTemplate(templateName) { 16 return $('template-collection-extension-error'). 17 querySelector('.' + templateName).cloneNode(true); 18 } 19 20 /** 21 * Checks that an Extension ID follows the proper format (i.e., is 32 22 * characters long, is lowercase, and contains letters in the range [a, p]). 23 * @param {string} id The Extension ID to test. 24 * @return {boolean} Whether or not the ID is valid. 25 */ 26 function idIsValid(id) { 27 return /^[a-p]{32}$/.test(id); 28 } 29 30 /** 31 * Creates a new ExtensionError HTMLElement; this is used to show a 32 * notification to the user when an error is caused by an extension. 33 * @param {Object} error The error the element should represent. 34 * @constructor 35 * @extends {HTMLDivElement} 36 */ 37 function ExtensionError(error) { 38 var div = cloneTemplate('extension-error-metadata'); 39 div.__proto__ = ExtensionError.prototype; 40 div.decorate(error); 41 return div; 42 } 43 44 ExtensionError.prototype = { 45 __proto__: HTMLDivElement.prototype, 46 47 /** @override */ 48 decorate: function(error) { 49 // Add an additional class for the severity level. 50 if (error.level == 0) 51 this.classList.add('extension-error-severity-info'); 52 else if (error.level == 1) 53 this.classList.add('extension-error-severity-warning'); 54 else 55 this.classList.add('extension-error-severity-fatal'); 56 57 var iconNode = document.createElement('img'); 58 iconNode.className = 'extension-error-icon'; 59 this.insertBefore(iconNode, this.firstChild); 60 61 var messageSpan = this.querySelector('.extension-error-message'); 62 messageSpan.textContent = error.message; 63 messageSpan.title = error.message; 64 65 var extensionUrl = 'chrome-extension://' + error.extensionId + '/'; 66 var viewDetailsLink = this.querySelector('.extension-error-view-details'); 67 68 // If we cannot open the file source and there are no external frames in 69 // the stack, then there are no details to display. 70 if (!extensions.ExtensionErrorOverlay.canShowOverlayForError( 71 error, extensionUrl)) { 72 viewDetailsLink.hidden = true; 73 } else { 74 var stringId = extensionUrl.toLowerCase() == 'manifest.json' ? 75 'extensionErrorViewManifest' : 'extensionErrorViewDetails'; 76 viewDetailsLink.textContent = loadTimeData.getString(stringId); 77 78 viewDetailsLink.addEventListener('click', function(e) { 79 extensions.ExtensionErrorOverlay.getInstance().setErrorAndShowOverlay( 80 error, extensionUrl); 81 }); 82 } 83 }, 84 }; 85 86 /** 87 * 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 89 * to populate the list. 90 * @constructor 91 * @extends {HTMLDivElement} 92 */ 93 function ExtensionErrorList(errors) { 94 var div = cloneTemplate('extension-error-list'); 95 div.__proto__ = ExtensionErrorList.prototype; 96 div.errors_ = errors; 97 div.decorate(); 98 return div; 99 } 100 101 ExtensionErrorList.prototype = { 102 __proto__: HTMLDivElement.prototype, 103 104 /** 105 * @private 106 * @const 107 * @type {number} 108 */ 109 MAX_ERRORS_TO_SHOW_: 3, 110 111 /** @override */ 112 decorate: function() { 113 this.contents_ = this.querySelector('.extension-error-list-contents'); 114 this.errors_.forEach(function(error) { 115 if (idIsValid(error.extensionId)) { 116 this.contents_.appendChild(document.createElement('li')).appendChild( 117 new ExtensionError(error)); 118 } 119 }, this); 120 121 if (this.contents_.children.length > this.MAX_ERRORS_TO_SHOW_) 122 this.initShowMoreButton_(); 123 }, 124 125 /** 126 * Initialize the "Show More" button for the error list. If there are more 127 * than |MAX_ERRORS_TO_SHOW_| errors in the list. 128 * @private 129 */ 130 initShowMoreButton_: function() { 131 var button = this.querySelector('.extension-error-list-show-more button'); 132 button.hidden = false; 133 button.isShowingAll = false; 134 var listContents = this.querySelector('.extension-error-list-contents'); 135 listContents.addEventListener('webkitTransitionEnd', function(e) { 136 if (listContents.classList.contains('active')) 137 listContents.classList.add('scrollable'); 138 }); 139 button.addEventListener('click', function(e) { 140 // Disable scrolling while transitioning. If the element is active, 141 // scrolling is enabled when the transition ends. 142 listContents.classList.toggle('active'); 143 listContents.classList.remove('scrollable'); 144 var message = button.isShowingAll ? 'extensionErrorsShowMore' : 145 'extensionErrorsShowFewer'; 146 button.textContent = loadTimeData.getString(message); 147 button.isShowingAll = !button.isShowingAll; 148 }.bind(this)); 149 } 150 }; 151 152 return { 153 ExtensionErrorList: ExtensionErrorList 154 }; 155 }); 156